Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I check if current code is part of a try-except-block?

I'm debugging a function that I wrote as part of some form of plug-in framework. The function does not appear to be doing what it should, and I have the suspicion that, somewhere up the stack, someone is catching exceptions, or raise (either a very specific or a very generic) exception and test what happens (but if it's swallowed, it still doesn't tell me where). I could enter the debugger and inspect the source code at every stack level. Is there a more direct way to list any try-except blocks that the current code may be part of — specifically, the try-part of any such block?

This is, of course, exclusively for debugging purposes.

like image 257
gerrit Avatar asked Apr 17 '19 13:04

gerrit


People also ask

When would you see a try except block in code?

A try and except block is used for error handling in Python. Try : Helps to test the code. If the code inside the try block is error free it is executed. Otherwise the error gets caught and control goes to the except block.

What happens if an exception occurs inside a try block?

When an exception occurs inside a try block, control goes directly to the catch block, so no other code will be executed inside the try block and the value of res will not change. Also when a method throws an exception it does not return anything.

How do you check for exceptions in Python?

Catching Exceptions in Python In Python, exceptions can be handled using a try statement. The critical operation which can raise an exception is placed inside the try clause. The code that handles the exceptions is written in the except clause.

When an error occurs within a try clause the code block will be executed?

When a catch -block is used, the catch -block is executed when any exception is thrown from within the try -block. For example, when the exception occurs in the following code, control transfers to the catch -block.


2 Answers

It's spectacularly possible I'm missing something here (I just eyeballed the dis.dis() output for the catcher function), but at least this catches simple cases of catching things on Python 3.7:

import sys
import dis


def are_we_being_caught():
    frame = sys._getframe(1)
    while frame:
        bytecode = dis.Bytecode(frame.f_code)
        except_stack = 0
        for instr in bytecode:
            if instr.opname == "SETUP_EXCEPT":  # Going into a try: except: block
                except_stack += 1
            elif instr.opname == "POP_EXCEPT":  # Exiting a try: except: block
                except_stack -= 1
            if instr.offset > frame.f_lasti:  # Past the current instruction, bail out
                break
        if except_stack:  # If we `break`ed in the middle of a SETUP/POP pair
            print(frame, "may be catching exceptions now")
        frame = frame.f_back


def catcher(fn):
    try:
        x = fn()
    except:
        x = None  # YOLO :D
    return x


def f1():
    return 8


def f2():
    are_we_being_caught()
    raise ValueError("foo")


print(catcher(f1))
print(catcher(f2))

outputs

8
<frame at 0x109d2d238, file 'so55729254.py', line 24, code catcher> may be catching exceptions now
None
like image 198
AKX Avatar answered Oct 23 '22 05:10

AKX


That's a pretty difficult one: internally, each frame maintains a stack of blocks but I don't think there's any API to access it (let alone from Python). So you'd have to walk the stackframes, disassemble the code to infer the span of your try blocks (see the SETUP_EXCEPT and SETUP_FINALLY opcodes), and see if the "current line" of the stack frame falls within that block.

like image 45
Masklinn Avatar answered Oct 23 '22 03:10

Masklinn