7

How to check if the current code is being executed while processing an exception? By 'while processing an exception' I mean within an except block, functions called from it, or if catching a specific exception type, the optional issubclass override within the exception's metaclass.

def sth():
    handling_exception = # ???
    if handling_exception:
        print 'handling an exception'
    else:
        print 'not handling an exception'


try:
    1 / 0
except:
    sth()  # prints 'handling an exception'

sth()  # prints 'not handling an exception'

Checking sys.exc_info() is not enough because exceptions tend to remain there - they are not cleared automatically. And enforcing sys.exc_clear() is impractical.

1
  • 1
    sys.exc_info() is cleared when you exit the frame where it was caught. Commented Aug 10, 2015 at 13:55

1 Answer 1

7

In Python 2, sys.exc_info() is cleared when you exit the frame where it was caught. So if you put the try..except in a function, exiting the function clears sys.exc_info(). In Python 3, the information is cleared when you exit the exception handler.

As such it can be used to detect if an exception was raised in this frame or any calling frame. If you need to somehow detect if an exception is being handled within the same frame as the try..except you can call sys.exc_clear() earlier to facilitate that.

There are no other methods of detecting if an exception was raised and handled.

Demo in Python 2:

>>> import sys
>>> from __future__ import print_function
>>> def baz():
...     print('Child frame', sys.exc_info())
... 
>>> def foo(clear=False):
...     bar(clear)
...     print('Calling frame', sys.exc_info())
... 
>>> def bar(clear=False):
...     try:
...         raise ValueError('bar')
...     except ValueError:
...         print('Handling an exception', sys.exc_info())
...         baz()
...     if clear: sys.exc_clear()
...     print('Frame that handled exception', sys.exc_info())
...     baz()
... 
>>> def baz():
...     print('Child frame', sys.exc_info())
... 
>>> foo()
Handling an exception (<type 'exceptions.ValueError'>, ValueError('bar',), <traceback object at 0x10075f6c8>)
Child frame (<type 'exceptions.ValueError'>, ValueError('bar',), <traceback object at 0x10075f6c8>)
Frame that handled exception (<type 'exceptions.ValueError'>, ValueError('bar',), <traceback object at 0x10075f6c8>)
Child frame (<type 'exceptions.ValueError'>, ValueError('bar',), <traceback object at 0x10075f6c8>)
Calling frame (None, None, None)
>>> foo(True)
Handling an exception (<type 'exceptions.ValueError'>, ValueError('bar',), <traceback object at 0x10075f290>)
Child frame (<type 'exceptions.ValueError'>, ValueError('bar',), <traceback object at 0x10075f290>)
Frame that handled exception (None, None, None)
Child frame (None, None, None)
Calling frame (None, None, None)

and in Python 3 (same function definitions):

>>> foo()
Handling an exception (<class 'ValueError'>, ValueError('bar',), <traceback object at 0x10f740e88>)
Child frame (<class 'ValueError'>, ValueError('bar',), <traceback object at 0x10f740e88>)
Frame that handled exception (None, None, None)
Child frame (None, None, None)
Calling frame (None, None, None)
Sign up to request clarification or add additional context in comments.

3 Comments

Unfortunately, doesn't seem to be cleared when exiting the except block and that's what I wanted: gist.github.com/pawlowskimichal/d58886a2ebe11a4b0416
@MichałPawłowski: yes, that illustrates what I am saying.
@MichałPawłowski: it is safe to call sys.exc_clear() when no exception was raised, why not just call that right after a try:..except:, perhaps even in a finally block if you are using a loop with break or continue statements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.