[Tutor] throwing exception across modules?

Steven D'Aprano steve at pearwood.info
Thu Sep 8 16:34:29 CEST 2011


James Hartley wrote:
> This is more a design question.
> 
> One lesson C++ programmers might learn is that throwing exceptions from
> within library code is fraught with problems because the internals of
> exception handling were spelled out in the C++ standard.  This manifests

Do you mean "weren't spelled out"?


> itself as problems when the library was compiled with one vendor's compiler,
> but the user of the library is using another compiler.
> 
> While I understand that Python doesn't suffer from this exact problem, are
> there other reasons that raising exceptions in a module only be caught by
> consumers of the module a bad idea?

Not at all. Python is designed to use exceptions as the primary error 
mechanism. Nearly every module and function you will use in Python will 
use exceptions to signal errors.

A few will also use exceptions to signal non-error exceptional cases, 
e.g. StopIteration is used by iterators when they run out of items.

Exceptions in Python aren't bolted on the top, they are fundamental to 
the way the language works. Even things like for loops work by catching 
exceptions.


> Any insight which can be shared would be most appreciated.

The only thing which sometimes catches out beginners is that they forget 
to use fully-qualified names for exceptions. E.g. you may need to do this:

import socket
try:
     ...
except socket.error:
     ...


instead of just "except error".

If possible, document which exceptions your code might throw. At least, 
document which exceptions you expect to throw under normal circumstances.

An exception in the top level of your module will be treated as fatal: 
it will prevent the module from being imported. (When I say fatal, I 
mean fatal for your module, not the caller: the caller can always catch 
the exception and skip the import.)

Think carefully about what exceptions you should use. Try to integrate 
with the standard Python exception hierarchy. See the docs for further 
details.

It's a matter of opinion whether you should use built-in exceptions 
as-is, or whether you subclass them. Subclassing can be as simple as:

class StatsError(ValueError):
     pass

or as complicated as you want. But in general, keep exceptions simple.

Try not to raise private exceptions where the caller will see them. In 
other words, if you define a private exception type by flagging the name 
with a leading single underscore:

class _InternalUseOnly(TypeError):  # single underscore means "private"
     pass

then never raise it unless you also catch it.



-- 
Steven


More information about the Tutor mailing list