Debugging

pdb

Das Modul pdb definiert einen interaktiven Quellcode-Debugger für Python-Programme. Es unterstützt die Verwendung von (bedingten) Breakpoints und die Schritt-für-Schritt Ausführung auf der Quellzeilenebene, die Inspektion von Stack-Frames, d.h. die Analyse des Aufrufstapels (stack), die Auflistung von Quellcode und die Auswertung von beliebigem Python-Code im Kontext eines Stack-Frames. Es unterstützt auch das Post-Mortem-Debugging, d.h. die Analyse des Codes nach dem Zeitpunkt eines kritischen Fehlers, der zum Absturz des Programms geführt hat und kann auch während der Programmsteuerung aufgerufen werden.

In [2]:
%%writefile pdbtest.py

def compute(s1,s2):
    s3 = s1 / s2   
    return s3         

a = 10
b = 2
c = 0
result = compute(a,b)
print(result)
result = compute(a,c)
print(result)
Overwriting pdbtest.py

Mit dem Befehl

python -m pdb pdbtest.py

lässt sich dann eine Debugger-Sitzung starten:

Dabei bedeuten die folgenden Zeichen die entsprechenden Debug-Kommandos h - help l - list current source code n - next line, don't step into s - step into next line p - print q - quit

    nik@jupyterhub:~$ python -m pdb pdbtest.py
    > /home/nik/pdbtest.py(2)<module>()
    -> def compute(s1,s2):
    (Pdb) h

    Documented commands (type help <topic>):
    ========================================
    EOF    c          d        h         list      q        rv       undisplay
    a      cl         debug    help      ll        quit     s        unt
    alias  clear      disable  ignore    longlist  r        source   until
    args   commands   display  interact  n         restart  step     up
    b      condition  down     j         next      return   tbreak   w
    break  cont       enable   jump      p         retval   u        whatis
    bt     continue   exit     l         pp        run      unalias  where

    Miscellaneous help topics:
    ==========================
    exec  pdb

    (Pdb) l
      1
      2  -> def compute(s1,s2):
      3         s3 = s1 / s2
      4         return s3
      5
      6     a = 10
      7     b = 2
      8     c = 0
      9     result = compute(a,b)
     10     print(result)
     11     result = compute(a,c)
    (Pdb) n
    > /home/nik/pdbtest.py(6)<module>()
    -> a = 10
    (Pdb) s
    > /home/nik/pdbtest.py(7)<module>()
    -> b = 2
    (Pdb) n
    > /home/nik/pdbtest.py(8)<module>()
    -> c = 0
    (Pdb) n
    > /home/nik/pdbtest.py(9)<module>()
    -> result = compute(a,b)
    (Pdb) p a,b,c
    (10, 2, 0)
    (Pdb) n
    > /home/nik/pdbtest.py(10)<module>()
    -> print(result)
    (Pdb) p result
    5.0
    (Pdb) n
    5.0
    > /home/nik/pdbtest.py(11)<module>()
    -> result = compute(a,c)
    (Pdb) s
    --Call--
    > /home/nik/pdbtest.py(2)compute()
    -> def compute(s1,s2):
    (Pdb) n
    > /home/nik/pdbtest.py(3)compute()
    -> s3 = s1 / s2
    (Pdb) p s1,s2
    (10, 0)
    (Pdb) s
    ZeroDivisionError: division by zero
    > /home/nik/pdbtest.py(3)compute()
    -> s3 = s1 / s2
    (Pdb) l
      1
      2     def compute(s1,s2):
      3  ->     s3 = s1 / s2
      4         return s3
      5
      6     a = 10
      7     b = 2
      8     c = 0
      9     result = compute(a,b)
     10     print(result)
     11     result = compute(a,c)
    (Pdb) q
    nik@jupyterhub:~$

%pdb

Für das Jupyter Notebook gibt es einen Cell-Magic Befehl %pdb, der im Falle eines Fehlerabbruchs den Debugger aufruft und so eine Post-Mortem-Analyse erlaubt:

In [3]:
%pdb

def compute(s1,s2):
    s3 = s1 / s2   
    return s3         

a = 10
b = 2
c = 0
result = compute(a,b)
print(result)
result = compute(a,c)
print(result)
Automatic pdb calling has been turned ON
5.0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-3-8c92baed900b> in <module>()
     10 result = compute(a,b)
     11 print(result)
---> 12 result = compute(a,c)
     13 print(result)

<ipython-input-3-8c92baed900b> in compute(s1, s2)
      2 
      3 def compute(s1,s2):
----> 4     s3 = s1 / s2
      5     return s3
      6 

ZeroDivisionError: division by zero
> <ipython-input-3-8c92baed900b>(4)compute()
      2 
      3 def compute(s1,s2):
----> 4     s3 = s1 / s2
      5     return s3
      6 

ipdb> h

Documented commands (type help <topic>):
========================================
EOF    cl         disable  interact  next    psource  rv         unt   
a      clear      display  j         p       q        s          until 
alias  commands   down     jump      pdef    quit     source     up    
args   condition  enable   l         pdoc    r        step       w     
b      cont       exit     list      pfile   restart  tbreak     whatis
break  continue   h        ll        pinfo   return   u          where 
bt     d          help     longlist  pinfo2  retval   unalias  
c      debug      ignore   n         pp      run      undisplay

Miscellaneous help topics:
==========================
exec  pdb

ipdb> p s1, s2
(10, 0)
ipdb> p a,b,c
(10, 2, 0)
ipdb> l
      1 get_ipython().magic('pdb')
      2 
      3 def compute(s1,s2):
----> 4     s3 = s1 / s2
      5     return s3
      6 
      7 a = 10
      8 b = 2
      9 c = 0
     10 result = compute(a,b)
     11 print(result)

ipdb> q
In [4]:
%%Mooc Video
Out[4]:
In [5]:
%%Mooc WebReference

pdb - The Python Debugger

https://docs.python.org/3/library/pdb.html

Hinweis: pdb - Der Python Debugger