Detecting an active exception

NeBlackCat lists at
Sat Jun 2 04:29:07 CEST 2007

Thanks Duncan - that does clear things up for me on how sys.exc_info() 
it actually works!

But it does seem that there is no way to test "am I currently running in 
the scope of handling of an exception", which is what I need. If there 
was, I could then rely on sys.exc_info() to examine the exception. I'm 
implementing something which has to do one thing if called during 
exception handling, and another otherwise (and there's no way to 
explicitly pass a flag to indicate the situation).

I'm surprised by there apparently not being such a test, I wonder if I 
should do a PEP to ask for this feature.

If anyone does know a way to do it in the current implementation, even 
by stack examining, I'd love to hear it! :-)

- John

Duncan Booth wrote:
> "NeBlackCat (lists)" <lists at> wrote:
>> Depending on what you read, sys.exc_info() is supposed to return 
>> (None,None,None) when there is no active exception, but it seems that
>> it returns info about the last exception when there isn't one
>> currently active.
>> For example:
>> try:
>>     a = a + 1
>> except:
>>     pass
>> print sys.exc_info()
>> produces:
>> <class exceptions.NameError at 0x009648D0>, <exceptions.NameError 
>> instance at 0x00B5E508>, <traceback object at 0x00B5E4E0>
>> Where the traceback object identifies the offending a=a+1 line (of
>> course). 
>> Is there another way of doing this? Note that I can't rely on using 
>> sys.exc_clear() in any solution, unfortunately.
> I think you have misunderstood the definition of when an exception is 
> 'currently active'. When an exception is caught, it remains currently 
> active so long as you are in the same function, or in a function which it 
> calls (i.e. so long as the current scope is still active). When you return 
> from that function the exception is no longer active and the previous 
> exception becomes active (or None if there has not been one or you have 
> used sys.exc_clear()).
> Try this:
> --------- -------------
> import sys
> def f():
>     try:
>         a = a + 1
>     except:
>         pass
>     g()
>     print "f", sys.exc_info()
> def g():
>     print "g", sys.exc_info()
> def h():
>     f()
>     print "h", sys.exc_info()
> h()
> ----------------------------
> The output is:
> g (<type 'exceptions.UnboundLocalError'>, UnboundLocalError("local variable 
> 'a' referenced before assignment",), <traceback object at 0x00A8B300>)
> f (<type 'exceptions.UnboundLocalError'>, UnboundLocalError("local variable 
> 'a' referenced before assignment",), <traceback object at 0x00A8B300>)
> h (None, None, None)
> As you can see the exception remains 'currently active' only until the 
> function in which it was caught returns.

More information about the Python-list mailing list