如何检查当前代码是否属于try-except-block的一部分?

时间:2019-04-17 13:57:31

标签: python debugging exception

我正在调试作为某种形式的插件框架一部分编写的函数。该函数似乎没有按照其应有的方式工作,我怀疑在堆栈的某个地方,有人正在捕获异常,或者引发(非常具体或非常通用的)异常并测试会发生什么(但是如果它是吞了下去,它仍然没有告诉我在哪里)。我可以进入调试器并在每个堆栈级别检查源代码。是否有一种更直接的方法来列出当前代码可能属于的任何try-except块,特别是任何此类块的try-part?

这当然是专门用于调试目的。

2 个答案:

答案 0 :(得分:9)

很可能我在这里遗漏了一些东西(我只是盯着dis.dis()函数的catcher输出),但是至少这捕获了一些简单的捕获问题的情况在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))

输出

8
<frame at 0x109d2d238, file 'so55729254.py', line 24, code catcher> may be catching exceptions now
None

答案 1 :(得分:1)

这是一个相当困难的工作:内部,每个框架都维护a stack of blocks,但我认为没有任何API可以访问它(更不用说Python了)。因此,您必须遍历堆栈帧,反汇编代码以推断try块的跨度(请参见SETUP_EXCEPTSETUP_FINALLY操作码),并查看堆栈帧的“当前行”落在那个方块内。