Python调试器中的列表理解范围错误

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

在调试代码时,我希望使用列表理解。但是,当我在函数中时,似乎无法从调试器中计算列表理解

我正在使用Python 3.4

脚本内容

$ 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]
>>>