python调试器中的所有变量都是未定义的

时间:2018-01-10 22:46:06

标签: python python-3.x debugging 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]

似乎每当我使用列表推导时,都存在未定义变量的问题。但是,如果我在打开Python后立即调用调试器,我没有观察到这种行为,一切运行正常。

为什么我有这个问题的任何想法?

4 个答案:

答案 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以及任何已知的可怕解决方法。
  • 不要使用user2357112建议的理解力。

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]