those darn exceptions

Steven D'Aprano steve+comp.lang.python at pearwood.info
Tue Jun 21 05:49:07 EDT 2011


On Tue, 21 Jun 2011 01:43:39 +0000, Chris Torek wrote:

> Exceptions are great, but...
> 
> Sometimes when calling a function, you want to catch some or even all
> the various exceptions it could raise.  What exceptions *are* those?

[snip much, much interactive code]

TL;DR

*wink*


Shorter version: "Is there any definitive list of what exceptions a 
function could raise?"

Shorter answer: "No."


[...]
> But how can I know a priori
> that os.kill() could raise OverflowError in the first place?

You can't. Even if you studied the source code, you couldn't be sure that 
it won't change in the future. Or that somebody will monkey-patch 
os.kill, or a dependency, introducing a new exception.

More importantly though, most functions are reliant on their argument. 
You *cannot* tell what exceptions len(x) will raise, because that depends 
on what type(x).__len__ does -- and that could be anything. So, in 
principle, any function could raise any exception.


[...]
> Functions have a number of special "__" attributes.  I think it might be
> reasonable to have all of the built-in functions, at least, have one
> more, perhaps spelled __exceptions__, that gives you a tuple of all the
> exceptions that the function might raise. Imagine, then:

Or the author of the function could document the exceptions that it 
raises. Either way, nothing prevents this list from getting out of sync 
with the reality of which exceptions could be raised.

Another question -- is the list of exceptions part of the function's 
official API? *All* of the exceptions listed, or only some of them?

Apart from your pylint example below -- which I don't find convincing in 
the least, see further comments later -- I don't see the point of this. 
You shouldn't have the attitude that "If a function could raise an 
exception, I'm going to catch it". You have to understand the 
circumstances that a function might raise, and decide whether or not you 
want it caught. Hint: almost always, the answer is you don't.

Either way, a mere list of exceptions doesn't give you much. This adds 
additional burden on the developer of the function, while giving little 
benefit to the user.


>     >>> os.kill.__doc__
>     'kill(pid, sig)\n\nKill a process with a signal.'
> 
> [this part exists]
> 
>     >>> os.kill.__exceptions__
>     (<type 'exceptions.OSError'>, <type 'exceptions.TypeError'>, <type
>     'exceptions.OverflowError'>, <type 'exceptions.DeprecationWarning'>)
> 
> [this is my new proposed part]
> 
> With something like this, a pylint-like tool could compute the
> transitive closure of all the exceptions that could occur in any
> function, by using __exceptions__ (if provided) or recursively finding
> exceptions for all functions called, and doing a set-union.

In general, you can't do this at compile-time, only at runtime. There's 
no point inspecting len.__exceptions__ at compile-time if len is a 
different function at runtime.



-- 
Steven



More information about the Python-list mailing list