dho*_*kas 2 python debugging python-3.x pdb
我在 Python 3.6 上遇到了一个非常奇怪的问题。在我的代码中间,我调用import pdb; pdb.set_trace()调试一些代码。
然后我无法正确调试,例如:
(Pdb) abc = 3
(Pdb) [abc for _ in range(2)]
*** NameError: name 'abc' is not defined
(Pdb) [abc, abc]
[3, 3]
Run Code Online (Sandbox Code Playgroud)
似乎每当我使用列表推导式时,都会出现未定义变量的问题。但是,如果我在打开 Python 后立即调用调试器,我不会观察到这种行为,一切运行正常。
任何想法为什么我有这个问题?
aba*_*ert 10
这被归档为bpo 问题 #21161,但以“无法修复”关闭。
\n\n根本问题正是user2357112\'s 答案所说的:理解1通过定义然后运行隐藏的嵌套函数来工作,但是在框架内的 pdb 中定义的函数不是真正的嵌套函数,并且无法从框架的范围。
\n\n有一些解决方法(其中一些在 bpo 问题中提到,或从该问题链接的地方),但它们都只是其中之一的巧妙变体:
\n\n(lambda abc: [abc for _ in range(2)])(abc)(换句话说,定义一个函数并显式传递局部值作为参数,而不是捕获它们。)[abc_ for abc_ in [abc] for _ in range(2)](换句话说,使用最外面的可迭代对象是一个参数这一事实。2)[loc[\'abc\'] for loc in [locals()] for _ in range(2)](换句话说,使用locals()[\'name\']而不是name, 并按上面的方式传递局部变量。)exec任何已知的同样可怕的解决方法来理解exec.1. 在 Python 2.x 中,列表推导式不存在这种情况,只有集合推导式和字典推导式以及生成器表达式才如此。但 Python 3 更改了列表推导式,使它们与其他推导式保持一致。
\n\n2. 用于理解的隐藏嵌套函数捕获封闭范围\xe2\x80\x94中的几乎所有名称,但最外层的可迭代(第一个中的for)是特殊的;它实际上是隐藏函数的参数,并且表达式在封闭范围内计算并作为参数值传递。
发生这种情况是因为列表推导式(大部分)是在嵌套作用域中计算的,并且在 pdb 中创建的嵌套作用域无法访问正在检查的作用域的局部变量。不过,它们可以访问全局变量,并且当您在打开 Python 后立即启动 pdb 时,您将在全局范围内运行它,因此abc您创建的内容是全局的。
这种情况也会发生在列表推导式 inexec和 in class 语句中。不幸的是,没有比“不要在那里使用列表理解”更好的解决方法了。
你可以试试下面的代码:
(Pdb) !import code; code.interact(local=vars())
Python 3.6.6 |Anaconda, Inc.| (default, Jun 28 2018, 17:14:51)
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> [abc for _ in range(2)]
Run Code Online (Sandbox Code Playgroud)
使用 Ctrl-D 返回到常规的 pdb 提示符。