2011-12-15 16 views
10

Esiste un pdb equivalente a disp in gdb?Python pdb (debugger) disp equivalente?

E.g. quando sto debug C usando gdb posso avere variabili stampate su ogni 'step' attraverso il codice digitando:

disp var 

Quando sto debug python usando PPB Vorrei funzionalità simili, ma disp non sembra per essere lì, la documentazione pdb python non sembra offrire un'alternativa - ma sembra un'omissione dispari?

+0

forse IPDB ha alcune funzionalità alternativa – bph

+0

In alternativa, se vi piace un bel interfaccia utente, si potrebbe desiderare di utilizzare [ pudb] (https://pypi.python.org/pypi/pudb). –

risposta

1

Durante il debug del pdb è possibile digitare il normale codice Python, oltre ai comandi di una sola lettera, quindi utilizzare solo print var dovrebbe funzionare per voi.

+0

significherebbe che pdb ristamperebbe automaticamente 'var' ogni volta che prendo' s' o 'n' allora? Non è sicuro che lo sarebbe, sembra lo stesso che digitare 'p var' per me. La domanda non è su come stampare una variabile usando il debugger, più su come posso usare pdb in modo più efficiente/efficace ... – bph

+0

Scusa - non - questo stampa solo una volta la variabile. – jsbueno

+0

ok - la mia nuova risposta dovrebbe farlo. – jsbueno

3

Il codice seguente utilizza le funzionalità di introspezione di Python per aggiungere due nuovi comandi al modulo PDB 0 basta inserire la funzione data e la sua chiamata in un modulo separato e importare questo modulo prima di iniziare il debugging. I comandi "undisp" aggiungono e ritraono gli orologi alle variabili.

Funziona tramite la monkeypatch del modulo pdb di Python, che è scritto in puro python.

# -*- coding: utf-8 -*- 

def patch_pdb(): 
    import pdb 

    def wrap(func): 
     def new_postcmd(self, *args, **kw): 
      result = func(self, *args, **kw) 
      if hasattr(self, "curframe") and self.curframe and hasattr(self, "watch_list"): 
       for arg in self.watch_list: 
        try: 
         print >> self.stdout, "%s: %s"% (arg, self._getval(arg)) + ", ", 
        except: 
         pass 
       self.stdout.write("\n") 
      return result #func(self, *args, **kw) 

     return new_postcmd 

    pdb.Pdb.postcmd = wrap(pdb.Pdb.postcmd) 

    def do_disp(self, arg): 
     if not hasattr(self, "watch_list"): 
      self.watch_list = [] 
     self.watch_list.append(arg) 

    pdb.Pdb.do_disp = do_disp 

    def do_undisp(self, arg): 
     if hasattr(self, "watch_list"): 
      try: 
       self.watch_list.remove(arg) 
      except: 
       pass 

    pdb.Pdb.do_undisp = do_undisp 

patch_pdb() 

if __name__ == "__main__": 
    # for testing 
    import pdb; pdb.set_trace() 
    a = 0 
    for i in range(10): 
     print i 
     a += 2 

Sfortunatamente, ho potuto solo visualizzare lo stato delle variabili come prima dell'esecuzione dell'ultimo comando. (Ho provato un po ', ma non è stato possibile eseguire il monkeypatch del modulo bdb, che è la base per il Pdb). È possibile provare e modificare i metodi in pdb.Pdb, bdb.Bdb o cmd.Cmd decorati da wrap per trovare uno che viene chiamato dopo che lo stato del frame di debug è stato modificato.

3

È possibile impostare alcuni alias che lo farà per voi:

alias n next;; p var 
alias s step;; p var 

Stampa di un intero elenco di nomi di variabili è lasciato come esercizio per il lettore. Sfortunatamente in questo modo significa che quando si invia al debugger una riga vuota, l'ultimo comando che esegue è p var anziché, ad esempio, n. Se si vuole risolvere questo, allora è possibile utilizzare questo set un po 'hacky di comandi Pdb invece:

!global __stack; from inspect import stack as __stack 
!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 s step;; p var;; !__pdb.lastcmd = "!__pdb.cmdqueue.append('s')" 
alias n next;; p var;; !__pdb.lastcmd = "!__pdb.cmdqueue.append('n')"