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