Will
Will

Reputation: 75635

handling exceptions in settrace 'return' calls

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?

Upvotes: 5

Views: 739

Answers (1)

ecatmur
ecatmur

Reputation: 157374

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')

Upvotes: 5

Related Questions