Python调试器中的列表理解范围错误
在调试代码时,我希望使用列表理解。但是,当我在函数中时,似乎无法从调试器中计算列表理解 我正在使用Python 3.4 脚本内容:Python调试器中的列表理解范围错误,python,debugging,python-3.x,list-comprehension,Python,Debugging,Python 3.x,List Comprehension,在调试代码时,我希望使用列表理解。但是,当我在函数中时,似乎无法从调试器中计算列表理解 我正在使用Python 3.4 脚本内容: $ cat test.py #!/usr/bin/python def foo(): x = [1, 2, 3, 3, 4] print(x) foo() 交互式调试: $ python3 -mpdb test.py
$ cat test.py
#!/usr/bin/python
def foo():
x = [1, 2, 3, 3, 4]
print(x)
foo()
交互式调试:
$ python3 -mpdb test.py
> /tmp/test.py(3)<module>()
-> def foo():
(Pdb) step
> /tmp/test.py(8)<module>()
-> foo()
(Pdb)
--Call--
> /tmp/test.py(3)foo()
-> def foo():
(Pdb)
> /tmp/test.py(4)foo()
-> x = [1, 2, 3, 3, 4]
(Pdb)
> /tmp/test.py(6)foo()
-> print(x)
(Pdb) p [x for _ in range(1)]
*** NameError: name 'x' is not defined
(Pdb) p x
[1, 2, 3, 3, 4]
$python3-mpdb test.py
>/tmp/test.py(3)()
->def foo():
(Pdb)步骤
>/tmp/test.py(8)()
->foo()
(Pdb)
--召唤--
>/tmp/test.py(3)foo()
->def foo():
(Pdb)
>/tmp/test.py(4)foo()
->x=[1,2,3,3,4]
(Pdb)
>/tmp/test.py(6)foo()
->打印(x)
(Pdb)p[x表示范围(1)]
***名称错误:未定义名称“x”
(Pdb)Px
[1, 2, 3, 3, 4]
为什么列表理解不知道
x
?如何从调试器评估列表理解,或实现等效行为?这是一个bug,还是调试器的某种基本限制?pdb
似乎在运行代码时使用了:
eval(compiled_code, globals(), locals())
(甚至可能只是eval(string,globals(),locals())
)
不幸的是,在编译时Python不知道局部变量。这通常并不重要:
import dis
但是,当引入另一个作用域时,例如使用对lambda
的列表理解时,编译效果很差:
dis.dis(compile("(lambda: x)()", "", "eval"))
#>>> 1 0 LOAD_CONST 0 (<code object <lambda> at 0x7fac20708d20, file "", line 1>)
#>>> 3 LOAD_CONST 1 ('<lambda>')
#>>> 6 MAKE_FUNCTION 0
#>>> 9 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
#>>> 12 RETURN_VALUE
注意这是一个LOAD\u GLOBAL
,其中x
在本地范围内
这里有一个完全愚蠢的黑客绕过它:
(Pdb) eval("(lambda: x)()", vars())
[1, 2, 3, 3, 4]
在Python3中,由于理解实现方式的改变,在访问任何非全局变量之前,必须在pdb中使用
interact
命令
>>> def foo(): [][0]
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in foo
IndexError: list index out of range
>>> import pdb;pdb.pm()
> <stdin>(1)foo()
(Pdb) x = 4
(Pdb) [x for _ in range(2)]
*** NameError: name 'x' is not defined
(Pdb) interact
*interactive*
>>> [x for _ in range(2)]
[4, 4]
>>>
>>def foo():[[0]
...
>>>foo()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第1行,在foo中
索引器:列表索引超出范围
>>>进口pdb;pdb.pm()
>(1)富()
(Pdb)x=4
(Pdb)[x代表范围(2)]
***名称错误:未定义名称“x”
(Pdb)互动
*互动的*
>>>[x代表范围(2)]
[4, 4]
>>>
更简单的例子:p(lambda:x)(
lambda指针给了我一个想法,我发现答案在这里同样适用。啊,那code.interact(locals=vars())
和我的eval
hack做的完全一样。哦,pdb
甚至有一个interact
命令,酷。这回答了你的问题吗?Aah,当它在模块级别上时,之所以能工作,是因为x
不在locals()
中。一开始我不明白。对于python2?在python2中,你不需要做任何事情,它只是多年来一直存在这个问题,并且认为它通常只是一个从未被修复的bug。@DaveLiu还是一个从未被修复的bug?交互
技巧被称为一种解决方法。我在qt app的一组跟踪中尝试了交互
,shell变得无响应,只响应QCoreApplication::exec:每当我按下enter键时,事件循环已经在运行。
(Pdb) eval("(lambda: x)()", vars())
[1, 2, 3, 3, 4]
>>> def foo(): [][0]
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in foo
IndexError: list index out of range
>>> import pdb;pdb.pm()
> <stdin>(1)foo()
(Pdb) x = 4
(Pdb) [x for _ in range(2)]
*** NameError: name 'x' is not defined
(Pdb) interact
*interactive*
>>> [x for _ in range(2)]
[4, 4]
>>>