我在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]
似乎每当我使用列表推导时,都存在未定义变量的问题。但是,如果我在打开Python后立即调用调试器,我没有观察到这种行为,一切运行正常。
为什么我有这个问题的任何想法?
答案 0 :(得分:3)
这是因为列表推导(主要)是在嵌套范围内进行评估,而在pdb中创建的嵌套范围无法访问被检查范围的局部变量。但是,他们可以访问全局变量,并且在打开Python后立即启动pdb时,您将在全局范围内运行它,因此您创建的abc
是全局的。
exec
和类语句中的列表推导也会发生这种情况。不幸的是,没有比“不使用列表推导”更好的解决方法。
答案 1 :(得分:2)
该文件以b.p.o. issue #21161格式归档,但以“无法修复”的格式关闭。
根本问题是user2357112's answer所说的:理解 1 通过定义然后运行隐藏的嵌套函数来工作,但是在框架内的pdb中定义的函数不是真正的嵌套函数并且无法访问框架范围内的变量。
有一些解决方法(其中一些在b.p.o问题中提及,或与该问题相关的地方),但是它们只是其中之一的巧妙变体:
(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中,对于列表推导(仅对set和dict推导以及生成器表达式)不正确。但是Python 3更改了列表理解,使它们与其他列表保持一致。
2。用于理解的隐藏嵌套函数几乎捕获了包围范围中的所有名称,但最外面的可迭代名称(第一个for
中的名称是特殊的);它实际上是隐藏函数的参数,表达式在封闭范围内求值并作为参数值传递。
答案 2 :(得分:2)
您可以尝试以下代码:
(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)]
使用Ctrl-D返回常规pdb提示符。
答案 3 :(得分:0)
与李攀峰的答案类似,但更简单的方法是在pdb中使用interact
。
以下是pdb失败且interact
在相同上下文中工作的示例。
Python 3.6.3 (default, Oct 4 2017, 06:09:05)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def do_comp():
... abc = 3
... import pdb; pdb.set_trace()
...
>>> do_comp()
--Return--
> <stdin>(3)do_comp()->None
(Pdb) [abc for _ in range(2)]
*** NameError: name 'abc' is not defined
(Pdb) interact
*interactive*
>>> [abc for _ in range(2)]
[3, 3]