2011-10-05 19 views
36

Sto debug di uno script python, e voglio vedere una variabile per un cambiamento (tanto come è possibile guardare un indirizzo di memoria in gdb). C'è un modo per fare questo?Come si guarda una variabile in PPB

+0

Puoi farlo in [pudb] (https://pypi.python.org/pypi/pudb) –

+0

@WayneWerner cura di aggiungere una risposta che mostra questo o il collegamento ai documenti? Sto cercando esplicitamente come farlo in 'pudb', ma è vuoto ... –

+0

@JeffWidman Sarebbe un'altra domanda - fammi sapere quando lo chiedi :) –

risposta

22

Ecco un modo davvero hacky per fare questo con pdb. Questi comandi possono essere inseriti nel tuo ~/.pdbrc per il caricamento automatico ogni volta che usi pdb.

!global __currentframe, __stack; from inspect import currentframe as __currentframe, stack as __stack 
!global __copy; from copy import copy as __copy 
!global __Pdb; from pdb import Pdb as __Pdb 
!global __pdb; __pdb = [__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self") for __framerec in __stack() if (__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self")).__class__ == __Pdb][-1] 

alias _setup_watchpoint !global __key, __dict, __val; __key = '%1'; __dict = __currentframe().f_locals if __currentframe().f_locals.has_key(__key) else __currentframe().f_globals; __val = __copy(%1) 

alias _nextwatch_internal next;; !if __dict[__key] == __val: __pdb.cmdqueue.append("_nextwatch_internal %1") 
alias _stepwatch_internal step;; !if __dict[__key] == __val: __pdb.cmdqueue.append("_stepwatch_internal %1") 

alias nextwatch __pdb.cmdqueue.extend(["_setup_watchpoint %1", "_nextwatch_internal"]) 
alias stepwatch __pdb.cmdqueue.extend(["_setup_watchpoint %1", "_stepwatch_internal"]) 

Questo aggiunge due comandi, nextwatch e stepwatch cui ciascun prendono un nome variabile varname come argomento. Faranno una copia dei variabile locale del frame corrente varname se possibile, e mantenere esecuzione next o step rispettivamente fino a che tale nome indica modifiche.

Questo funziona in CPython 2.7.2 ma si basa su alcuni interni pdb, quindi si romperà probabilmente altrove.

+0

Ho copiato le macro nel mio file ~/.pdbrc. Comunque pdb mi dice: NameError 'nextwatch' non è stato risolto. Lo faccio cadere così: "nextwatch '(var) –

+0

Io uso python 3.5, mac, e sembra che' .pdbrc' non funzioni Anche quando incollo il codice sopra in '(pdb):' environment, quando I esegui 'stepwatch' o' nextwatch', dice '__dict' e altri non sono definiti.Potresti aggiornare il tuo codice per python 3.5? grazie – Daniel

+0

Come accennato, questo probabilmente non funzionerà in alcune altre versioni di Python. per pubblicare una versione di Python 3.5 come nuova risposta –

16

Per la visualizzazione di una variabile quando si colpisce un punto di interruzione , è possibile utilizzare il comando commands. Per esempio. stampa some_variable quando si colpisce il punto di interruzione n. 1 (canonical example from pdb doc).

(Pdb) commands 1 
(com) print some_variable 
(com) end 
(Pdb) 
+0

Questa dovrebbe essere la risposta migliore: semplice, diretta, ti insegna una funzione precisa di pdb - i comandi di breakpoint –

+1

Mentre può essere utile, non risponde direttamente alla domanda , che desidera controllare le modifiche alle variabili e quindi interromperle, non solo visualizzare lo stato di una variabile nei punti di interruzione preimpostati. – kmantel

8

Per Python 3:

è possibile utilizzare display funzionalità del PPB

Una volta raggiunto il punto di interruzione è sufficiente digitare

IPDB>visualizzazioneespressione

esempio:

ipdb> display instance 
display instance: <AppUser: dmitry4> 
ipdb> display instance.id 
display instance.id: 9 
ipdb> display instance.university 
display instance.university: <University: @domain.com> 

ipdb> display 

Currently displaying: 
instance.university: <University: @domain.com> 
instance.id: 9 
instance: <AppUser: dmitry4> 
ipdb> 

come si può vedere, ogni volta che si digita display - stamperà tutti i tuoi orologi (espressioni). È possibile utilizzare la funzione di visualizzazione per rimuovere determinati orologi.

È inoltre possibile utilizzare pp espressione al prettyprint l'espressione (molto utile)

6

Una possibile soluzione è quella di utilizzare pdb++:

pip install pdbpp 

Poi "marchio" l'oggetto che si desidera guardare con il decoratore @pdb.break_on_setattr:

from pdb import break_on_setattr 
@break_on_setattr('bar') 
class Foo(object): 
    pass 

f = Foo() 
f.bar = 42 # the program breaks here 

Qui pdb wil interrompo qualsiasi modifica dell'attributo bar su qualsiasi oggetto Foo.

Avvertenze
Solo invocazioni del sottostante __setattr__ -Metodo attiverà il punto di interruzione.Ciò significa che f.bar = 'XYZ' e setattr(f, 'XYZ') funzionerà, ma la manipolazione del bar -oggetto non attivano il punto di interruzione:

f.bar = [] 
f.bar.append(7) # will NOT trigger breakpoint 

f.bar = 2 
f.bar += 5  # will trigger breakpoint 

Nota: @break_on_setattr non è parte dello standard pdb -module. pdb è sovrascritto/scimmia-patchato dal pacchetto pdbpp.

Problemi correlati