In Python 2.x, the frame object passed into a settrace handler had an f_exc_type attribute.
In Python 3.x, this f_exc_type has been removed.
If a function is propagating an exception, the trace 'return' is called but the argument is None and sys.exc_info() is (None,None,None). This is described in the docs:
[return]A function (or other code block) is about to return. The local trace function is called; arg is the value that will be returned, or None if the event is caused by an exception being raised. The trace function’s return value is ignored.
In Python 3, how can a tracer determine in a return hook that an exception is being propagated? How can it differentiate it from a function returning None normally?
This does seem fairly broken. It's a bit of a hack, but you can tell the difference by looking at the bytecode for the last instruction:
import opcode
def tracer(frame, event, arg):
if event == 'return':
if arg is not None or (opcode.opname[frame.f_code.co_code[frame.f_lasti]]
in ('RETURN_VALUE', 'YIELD_VALUE')):
print('exit via return', arg)
else:
print('exit via exception')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With