2011-12-15 19 views
10

Czy istnieje odpowiednik pdb dla disp w gdb?Python pdb (debugger) disp equivalent?

E.g. kiedy jestem debugowanie C za pomocą gdb mogę mieć zmienne nadrukowane na każdym kroku „” za pomocą kodu wpisując:

disp var 

Kiedy jestem debugowanie python przy użyciu WPB Chciałbym podobną funkcjonalność, ale nie wydaje disp być tam, dokumentacja pdb Pythona nie wydaje się oferować alternatywy - ale wydaje się dziwne pominięcie?

+0

może ipdb ma jakąś alternatywną funkcjonalność – bph

+0

jako alternatywa, jeśli lubisz ładne UI, możesz użyć [ pudb] (https://pypi.python.org/pypi/pudb). –

Odpowiedz

1

Podczas debugowania pdb możesz wpisać normalny kod Pythona, poza poleceniami jednoliterowymi - więc po prostu użyj print var powinien zadziałać.

+0

Czy oznaczałoby to, że pdb automatycznie przedrukowywałoby 'var' za każdym razem, gdy uderzyłem' s' lub 'n', a następnie? Nie jestem pewien, czy to by było, wydaje mi się takie samo jak wpisanie "p var" do mnie. Nie chodzi o to, jak wydrukować zmienną za pomocą debuggera, więcej o tym, jak mogę wydajniej/efektywniej używać pdb ... – bph

+0

Niestety - nie - to wypisuje zmienną tylko raz. – jsbueno

+0

ok - moja nowa odpowiedź powinna to zrobić. – jsbueno

3

Kod poniżej wykorzystuje funkcje introspekcji Pythona do dodania dwóch nowych poleceń do modułu PDB 0 wystarczy umieścić daną funkcję i jej wywołanie w oddzielnym module i zaimportować ten moduł przed rozpoczęciem debugowania - powinieneś mieć "disp" Polecenia 'i' undisp 'dodają i wycofują zegarki do zmiennych.

Działa przez monkeypatching modułu pdb Pythona, który jest napisany czystym pythonem.

# -*- 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 

Niestety, mogłem tylko sprawić, aby wyświetlał stan zmiennych w miejscu, w którym poprzednio wykonywał ostatnie polecenie. (Próbowałem trochę, ale monkeypatching modułu bdb, który jest podstawą dla Pdb, również nie działa tak dobrze). Możesz spróbować zmienić metody w plikach pdb.Pdb, bdb.Bdb lub cmd.Cmd, które są dekorowane przez wrap, aby znaleźć taki, który jest wywoływany po zmianie stanu debugowanego klatki.

3

Można skonfigurować kilka aliasów, który zrobi to za ciebie:

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

Drukowanie całą listę nazw zmiennych pozostawiamy jako ćwiczenie dla czytelnika. Niestety zrobienie tego w ten sposób oznacza, że ​​po wysłaniu debuggera pustym wierszem, "ostatnie polecenie", które wykonuje, to raczej p var niż na przykład n. Jeśli chcesz naprawić, a następnie można użyć tej nieco hacky zestaw poleceń Pdb zamiast:

!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')"