python 调试器中的所有变量都未定义
all variables are undefined in python debugger
我在 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 后立即调用调试器,我没有观察到这种行为,一切运行正常。
知道我为什么会遇到这个问题吗?
发生这种情况是因为列表理解(大部分)在嵌套范围内进行评估,而在 pdb 中创建的嵌套范围无法访问正在检查的范围的局部变量。但是,它们可以访问全局变量,并且当您在打开 Python 后立即启动 pdb 时,您 运行 它处于全局范围内,因此您创建的 abc
是全局的。
exec
和 class 语句中的列表理解也会发生这种情况。不幸的是,没有比 "don't use list comprehensions there".
更好的解决方法了
归档为 b.p.o. issue #21161,但关闭为 "won't fix"。
根本问题正是 所说的:Comprehensions1 通过定义然后 运行 一个隐藏的嵌套函数来工作,但是在 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
,并像上面那样获取locals。)
- 使用
exec
加上任何已知的同样可怕的解决方法来理解 exec
。
- 不要像 user2357112 所建议的那样使用推导式。
1。在 Python 2.x 中,列表推导式并非如此,仅集和字典推导式以及生成器表达式。但是 Python 3 更改了列表推导式以使其与其他推导式保持一致。
2。理解的隐藏嵌套函数从封闭范围捕获 几乎 所有名称——但最外层的可迭代对象(第一个 for
中的那个)是特殊的;它实际上是隐藏函数的参数,表达式在封闭范围内计算并作为参数值传递。
您可以试试下面的代码:
(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 return 进入常规 pdb 提示符。
类似于 Panfeng Li 的回答,但更简单的方法是在 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]
我在 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 后立即调用调试器,我没有观察到这种行为,一切运行正常。
知道我为什么会遇到这个问题吗?
发生这种情况是因为列表理解(大部分)在嵌套范围内进行评估,而在 pdb 中创建的嵌套范围无法访问正在检查的范围的局部变量。但是,它们可以访问全局变量,并且当您在打开 Python 后立即启动 pdb 时,您 运行 它处于全局范围内,因此您创建的 abc
是全局的。
exec
和 class 语句中的列表理解也会发生这种情况。不幸的是,没有比 "don't use list comprehensions there".
归档为 b.p.o. issue #21161,但关闭为 "won't fix"。
根本问题正是
有一些解决方法(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
,并像上面那样获取locals。)- 使用
exec
加上任何已知的同样可怕的解决方法来理解exec
。 - 不要像 user2357112 所建议的那样使用推导式。
1。在 Python 2.x 中,列表推导式并非如此,仅集和字典推导式以及生成器表达式。但是 Python 3 更改了列表推导式以使其与其他推导式保持一致。
2。理解的隐藏嵌套函数从封闭范围捕获 几乎 所有名称——但最外层的可迭代对象(第一个 for
中的那个)是特殊的;它实际上是隐藏函数的参数,表达式在封闭范围内计算并作为参数值传递。
您可以试试下面的代码:
(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 return 进入常规 pdb 提示符。
类似于 Panfeng Li 的回答,但更简单的方法是在 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]