a_g*_*est 7 python breakpoints exception python-3.x pdb
考虑以下示例:
try:
raise ValueError('test')
except ValueError as err:
breakpoint() # at this point in the debugger, name 'err' is not defined
Run Code Online (Sandbox Code Playgroud)
在这里,进入断点后,调试器无权访问绑定到的异常实例err:
$ python test.py
--Return--
> test.py(4)<module>()->None
-> breakpoint()
(Pdb) p err
*** NameError: name 'err' is not defined
Run Code Online (Sandbox Code Playgroud)
为什么会这样?如何访问异常实例?目前我正在使用以下解决方法,但感觉很尴尬:
$ python test.py
--Return--
> test.py(4)<module>()->None
-> breakpoint()
(Pdb) p err
*** NameError: name 'err' is not defined
Run Code Online (Sandbox Code Playgroud)
有趣的是,使用此版本,我还可以err在调试器中向上移动一帧时访问绑定异常:
$ python test.py
--Return--
> test.py(5)_tmp()->None
-> breakpoint()
(Pdb) up
> test.py(6)<module>()
-> _tmp()
(Pdb) p err
ValueError('test')
Run Code Online (Sandbox Code Playgroud)
dis在下面我比较了两个版本,一个breakpoint直接使用,另一个将其包装在自定义函数中_breakpoint:
try:
raise ValueError('test')
except ValueError as err:
def _tmp():
breakpoint()
_tmp()
# (lambda: breakpoint())() # or this one alternatively
Run Code Online (Sandbox Code Playgroud)
dis除了一些内存位置和函数名称之外,输出是相似的:
所以它必须是允许pdb引用绑定异常实例的附加堆栈帧。但是不清楚为什么会这样,因为在except块内任何东西都可以引用绑定的异常实例。
breakpoint()不是断点,因为它在此函数调用的确切位置停止执行。相反,它是一种简写import pdb; pdb.set_trace(),它将在下一行代码(它sys.settrace在幕后调用)停止执行。由于except块内没有更多代码,因此在退出该块后执行将停止,因此名称err已被删除。通过在except块之后添加一行代码可以更清楚地看到这一点:
try:
raise ValueError('test')
except ValueError as err:
breakpoint()
print()
Run Code Online (Sandbox Code Playgroud)
这给出了以下内容:
$ python test.py
> test.py(5)<module>()
-> print()
Run Code Online (Sandbox Code Playgroud)
这意味着解释器即将执行第print()5 行中的语句,并且它已经执行了之前的所有内容(包括删除 name err)。
当使用另一个函数来包装时,breakpoint()解释器将在该return函数发生时停止执行,因此该except块尚未退出(并且err仍然可用):
$ python test.py
--Return--
> test.py(5)<lambda>()->None
-> (lambda: breakpoint())()
Run Code Online (Sandbox Code Playgroud)
except块的退出也可以通过在pass之后放置一个额外的语句来延迟breakpoint():
$ python test.py
> test.py(5)<module>()
-> print()
Run Code Online (Sandbox Code Playgroud)
这导致:
$ python test.py
> test.py(5)<module>()
-> pass
(Pdb) p err
ValueError('test')
Run Code Online (Sandbox Code Playgroud)
请注意,pass必须放在单独的行上,否则将被跳过:
$ python test.py
--Return--
> test.py(4)<module>()->None
-> breakpoint(); pass
(Pdb) p err
*** NameError: name 'err' is not defined
Run Code Online (Sandbox Code Playgroud)
注意--Return--这意味着解释器已经到达模块的末尾。