Semantics of propagated exceptions

Thomas Lotze thomas at thomas-lotze.de
Fri Jul 21 05:57:14 EDT 2006


Hi,

I wonder how to solve the following problem the most pythonic way:

Suppose you have a function f which, as part of its protocol, raises some
standard exception E under certain, well-defined circumstances. Suppose
further that f calls other functions which may also raise E. How to best
distinguish whether an exception E raised by f has the meaning defined by
the protocol or just comes from details of the implementation?

As an example, let's inherit from dict and replace __getitem__. It is
supposed to raise a KeyError if an item is not found in the mapping. But
what if it does some magic to use default values:

def __getitem__(self, key):
	if key in self:
		return self[key]
	defaults = foobar["default"]
	return defaults[key]

If "default" is not in foobar, a KeyError is raised by that lookup and
propagates to the calling code. However, the problem is not "key can't be
found" but "I'm too stupid to find out whether key can be found". In a web
context where key identifies the resource requested, this might make the
difference between a 404 "Not found" and a 500 "Internal server error"
response.

Several solutions come to mind, neither of which I'm satisfied with:

- f might catch E exceptions from the implementation and raise some other
error in their stead, maybe with an appropriate message or treating the
traceback in some helpful way. This destroys the original exception.

- f might catch and re-raise E exceptions, setting some flag on them that
identifies them as protocol exceptions or not. This requires calling code
to know about the flag.

- Calling code might guess whether the exception comes from some inner
working of f from how deep in the calling stack the exception originated.
Obviously, this will not be easy or not even work at all if f calls
related functions which might also raise E with the protocol semantics.
This requires calling code to do some magic but keeps f from having to
catch and raise exceptions all over the place.

Some gut feeling tells me the first option is preferrable, but I'ld like
to read your opinions and maybe other alternatives.

-- 
Thomas





More information about the Python-list mailing list