Python - Debug

Python

Chi prima chi dopo, tutti ad un certo punto si sono ritrovati a dover fare il debug del proprio codice, o di un codice che hanno ereditato da terzi. Passare in rassegna ogni istruzione e ogni cambiamento di valore delle variabili per capire perchè ad un certo punto ci ritroviamo con una NullPointerException nei log, o altri simpatici accadimenti che scandiscono la nostra giornata di lavoro/studio.

Diversi IDE contengono un debugger completo nella loro installazione base (Eclipse, NetBeans, ecc...) che vi consente di scorrere interattivamente il codice durante la fase di sviluppo.
Per quanto riguarda Python, come già un po' detto nella nostra introduzione, il modulo ipdb consente di impostare nel vostro codice dei punti in cui poter interagire col flusso di esecuzione tramite una shell interattiva simile a quella di ipython.

Uno dei vantaggi di un debugger come ipdb è quello di poter essere eseguito da linea di comando, senza necessità di una IDE grafica. Potrete perciò controllare il flusso di esecuzione del vostro programma Python installato su un server remoto direttamente da ssh.

Purtroppo la documentazione di ipdb non è particolarmente completa. L'articolo che state leggendo nasce perciò da un mix di esperienza personale e di guide e domande trovate navigando tra forum e blog.

Iniziamo perciò con l'installazione digitando da terminale:
pip install ipdb

Debug di base

Per utilizzare il modulo ipdb dovrete per prima cosa includerlo nei file .py per i quali volete fare il debug:
import ipdb
Per impostare un punto nel vostro codice dal quale si apra l'interfaccia interattiva di ipdb, dovrete utilizzare il metodo ipdb.set_trace()

ipdb_shell_interattiva

A schermo vi sarà stampata l'istruzione che segue set_trace, con la riga precedente e successiva. Per avere un contesto più ampio del flusso di codice, vi basterà digitare l sul prompt di ipdb:

ipdb_l

Impostare breakpoint

Con il comando b potete impostare breakpoint utilizzando come riferimento il numero di riga (preceduto dal path del file .py se diverso da quello dove si trova il flusso in questo momento) o il nome di un metodo. In quest'ultimo caso, il breakpoint sarà posizionato alla prima riga eseguibile del metodo. Per stampare l'elenco dei breakpoint, basta utilizzare il comando b senza argomenti.

ipdb_breakpoint

Il comando b accetta come secondo argomento anche una espressione booleana. In questo modo, l'esecuzione del flusso si fermerà al breakpoint solo se tale condizione risulterà soddisfatta. Questo strumento può essere utile per fermarsi all'interno di un ciclo molto lungo solo se si verifica una particolare eventualità.

Per eliminare i breakpoint si utilizza il comando cl per "clear", seguito dall'indice identificativo del breakpoint da eliminare. Con i comandi enable e disable potrete invece abilitare o disabilitare i breakpoint.


Esecuzione del flusso

Per continuare con l'esecuzione del codice avete adesso quattro alternative:

  • n: comando "next", il flusso continua con la successiva istruzione del metodo in cui ci troviamo
  • s: comando "step", il flusso continua con la successiva istruzione; a differenza di "next", con "step" potete entrare nel flusso delle funzioni chiamate
  • c: comando "continue", continua l'esecuzione del flusso fino a quando non incontra un nuovo breakpoint (se non ce ne sono, continua l'esecuzione fino alla fine)
  • j + riga: comando "jump", continua l'esecuzione del flusso saltando alla riga di codice riga
  • q: comando "quit", si esce dal debugger


Informazioni sulle variabili

Esistono più possibilità per ispezionare le variabili:

  • p variabile: esegue lo stesso risultato di un print variabile
  • pinfo variabile: stampa il contenuto della variabile e altre informazioni sulla stessa

ipdb_variabili

Nell'immagine avrete notato che il comando pinfo stampa l'attributo Namespace: Locals. La variabile squadre rientra infatti tra le variabili locali della funzione main dove ci troviamo in questo momento.
Con i comandi pp globals() e pp locals() potete stampare tutti gli "oggetti" globali e locali del programma.

ipdb_locals

ipdb_globals

Molto utile risulta anche il comando a per "args", comando che stampa a video l'elenco degli argomenti passati al metodo in cui ci troviamo in questo momento.

Utilizzare lo stacktrace

L'esempio a cui sto facendo riferimento è lo script che avevo presentato in questo articolo. Se lo avete già visto, avrete notato che non è un progetto enorme, dove è facile perdersi. Tuttavia, se avete bisogno di capire dove siete posizionati nello stacktrace del vostro progetto, vi basterà digitare il comando w per "where":

ipdb_stacktrace

Ora che potete vedere lo stacktrace, con i comandi u up e d down potrete salire o scendere nello stack per continuare l'esecuzione.


Come sempre vi invito a commentare per domande, dubbi e correzioni. Lascio l'elenco delle guide e dei topic utilizzati per redigere l'articolo.

Alessio Antonielli

Ingegnere informatico, appassionato di cinema, musica, videogiochi e serie tv. Insomma, le solite cose che vi aspettereste da un ex studente di Ingegneria Informatica, giusto per rafforzare lo stereotipo…

Python - Debug ultima modifica: 2016-10-18T11:24:52+01:00 da Alessio Antonielli


Advertisment ad adsense adlogger