2014-06-10 20 views
12

In Debuggen von meinem Code, ich möchte ein Listenverständnis verwenden. Es scheint jedoch, dass ich ein Listenverständnis nicht vom Debugger aus beurteilen kann, wenn ich mich in einer Funktion befinde.List Verständnis Verständnis Fehler von Python Debugger

Ich benutze Python 3.4.

Script Inhalt:

$ cat test.py 
#!/usr/bin/python 

def foo(): 
    x = [1, 2, 3, 3, 4] 

    print(x) 

foo() 

Interactive Debugging:

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

Warum ist x unbekannt in der Liste Verständnis? Wie kann ich ein Listenverständnis vom Debugger aus bewerten oder ein gleichwertiges Verhalten erreichen? Ist das ein Fehler oder ist es eine Art grundsätzliche Einschränkung für den Debugger?

+0

@Veedrac Huh, ich habe gerade in einem kleinen Testskript realisiert, dass es dort funktioniert. Ich werde etwas graben und mit einem kleinen ausführbaren Script zurückkommen! – gerrit

+1

@Veedrac Edited um genau das hinzuzufügen. – gerrit

+0

Einfacheres Beispiel: 'p (Lambda: x)()' – Veedrac

Antwort

11

In Python 3, haben Sie die interact Befehl in pdb verwenden, bevor Sie aufgrund einer Änderung alle nicht-globalen Variablen zugreifen können in der Art und Weise, wie das Verständnis umgesetzt wird.

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

pdb scheint den Code mit laufen:

eval(compiled_code, globals(), locals()) 

(oder vielleicht sogar nur eval(string, globals(), locals())).

Leider weiß Python bei der Kompilierung nicht über die lokalen Variablen. Dies gilt normalerweise nicht egal:

import dis 
dis.dis(compile("x", "", "eval")) 
#>>> 1   0 LOAD_NAME    0 (x) 
#>>>    3 RETURN_VALUE 

aber wenn ein anderer Umfang eingeführt wird, wie mit einer Liste Verständnis von lambda, das kompiliert schlecht:

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 
# The code of the internal lambda 
dis.dis(compile("(lambda: x)()", "", "eval").co_consts[0]) 
#>>> 1   0 LOAD_GLOBAL    0 (x) 
#>>>    3 RETURN_VALUE 

Beachten Sie, wie das ist ein LOAD_GLOBAL wo x ist in der lokalen sco pe.


ist hier ein total dumm Hack um es zu bekommen:

(Pdb) eval("(lambda: x)()", vars()) 
[1, 2, 3, 3, 4] 
+0

Aah, und der Grund, warum es funktioniert, wenn es auf einer Modulebene ist, ist, weil 'x' nicht in' locals() 'ist. Das habe ich zuerst nicht verstanden. – gerrit