python - except 子句中的断点无权访问绑定(bind)异常

标签 python python-3.x exception breakpoints pdb

考虑以下示例:

try:
    raise ValueError('test')
except ValueError as err:
    breakpoint()  # at this point in the debugger, name 'err' is not defined
在这里,在 breakpoint 之后输入,调试器无权访问绑定(bind)到 err 的异常实例:
$ python test.py 
--Return--
> test.py(4)<module>()->None
-> breakpoint()
(Pdb) p err
*** NameError: name 'err' is not defined
为什么会这样?如何访问异常实例?目前我正在使用以下解决方法,但感觉很尴尬:
try:
    raise ValueError('test')
except ValueError as err:
    def _tmp():
        breakpoint()
    _tmp()
    # (lambda: breakpoint())()  # or this one alternatively
有趣的是,使用这个版本,我还可以访问绑定(bind)异常 err在调试器中向上移动一帧时:
$ python test.py 
--Return--
> test.py(5)_tmp()->None
-> breakpoint()
(Pdb) up
> test.py(6)<module>()
-> _tmp()
(Pdb) p err
ValueError('test')
通过 dis 进行拆卸
下面我比较了两个版本,一个使用 breakpoint直接和另一个将其包装在自定义函数中 _breakpoint :
def _breakpoint():
    breakpoint()

try:
    raise ValueError('test')
except ValueError as err:
    breakpoint()   # version (a), cannot refer to 'err'
    # _breakpoint()  # version (b), can refer to 'err'
dis 的输出当然除了一些内存位置和函数名称之外是相似的:
diff
所以它必须是允许 pdb 的附加堆栈帧引用绑定(bind)的异常实例。但是不清楚为什么会这样,因为在 except阻止任何东西都可以引用绑定(bind)的异常实例。

最佳答案

breakpoint() 不是断点,因为它会在此函数调用的确切位置停止执行。相反,它是 import pdb; pdb.set_trace() 的简写。这将在下一行代码处停止执行(它在幕后调用 sys.settrace )。由于 except 内没有更多代码块,执行将在该 block 退出后停止,因此名称 err已被删除。通过在 except 之后添加一行代码可以更清楚地看到这一点。堵塞:

try:
    raise ValueError('test')
except ValueError as err:
    breakpoint()
print()
这给出了以下内容:
$ python test.py 
> test.py(5)<module>()
-> print()
这意味着解释器即将执行 print()第 5 行中的语句,并且它已经执行了它之前的所有内容(包括删除名称 err )。
当使用另一个函数来包装 breakpoint()然后解释器将在 return 处停止执行。该函数的事件,因此 except block 尚未退出(err 仍然可用):
$ python test.py 
--Return--
> test.py(5)<lambda>()->None
-> (lambda: breakpoint())()
except 的退出也可以通过添加一个额外的 pass 来延迟 block 。 breakpoint() 之后的声明:
try:
    raise ValueError('test')
except ValueError as err:
    breakpoint()
    pass
这导致:
$ python test.py 
> test.py(5)<module>()
-> pass
(Pdb) p err
ValueError('test')
请注意 pass必须放在单独的行上,否则将被跳过:
$ python test.py 
--Return--
> test.py(4)<module>()->None
-> breakpoint(); pass
(Pdb) p err
*** NameError: name 'err' is not defined
注意 --Return--这意味着解释器已经到达模块的末尾。

关于python - except 子句中的断点无权访问绑定(bind)异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62796591/

相关文章:

python - 将 AST 节点转换为向量/数字

python - 如何解析远程文档?

c++ - 输出窗口显示抛出的异常

python - 链接按钮以运行 .py 文件

python - 如何使用 GTK 获取正在运行的应用程序的列表?

python-3.x - 如何使用 Python 中的键扩展字典中的值

java - IllegalArgumentException 未被捕获或丢失某些内容

c# - Entity Framework 的重复键异常?

python - 我想对 ${ 和 } 之间的字符串进行切片

python - on_load 清除某个 channel 的所有消息