Suggerimenti per il debug di Python [chiuso]


164

Quali sono i tuoi migliori consigli per il debug di Python?

Ti preghiamo di non elencare un particolare debugger senza dire cosa può effettivamente fare.

Relazionato


Risposte:


139

PDB

È possibile utilizzare il modulo pdb, inserire pdb.set_trace()ovunque e funzionerà come punto di interruzione.

>>> import pdb
>>> a="a string"
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) p a
'a string'
(Pdb)

Per continuare l'esecuzione utilizzare c(o conto continue).

È possibile eseguire espressioni Python arbitrarie usando pdb. Ad esempio, se trovi un errore, puoi correggere il codice, quindi digitare un'espressione di tipo per avere lo stesso effetto nel codice in esecuzione

ipdb è una versione di pdb per IPython . Permette l'uso di pdb con tutte le funzionalità di IPython incluso il completamento della scheda.

È anche possibile impostare pdb per l'esecuzione automatica su un'eccezione non rilevata.

Pydb è stato scritto per essere una versione avanzata di Pdb. Benefici?


Ecco un articolo sull'uso di pdb
sontek

Personalmente, mi piace meglio l' ipdb .
Sardathrion - contro l'abuso di SE

1
Apparentemente c'è una riscrittura di pydb chiamata pydbgr
Ehtesh Choudhury,

SublimeText ha un ottimo plugin per aggiungere punti di interruzione Python al codice: sublime.wbond.net/packages/Python%20Breakpoints
Dennis Golomazov,

Se stai sviluppando un'applicazione web, aggiungi una vista myserver.com/pdbin modalità debug che lo fa semplicemente import pdb; pdb.set_trace(). Se stai usando Flask / Werkzeug che ha un debugger interattivo, puoi anche avere una vista che lo fa assert False.
osa,

78

http://pypi.python.org/pypi/pudb , un debugger Python a schermo intero basato su console.

Il suo obiettivo è fornire tutte le bellezze dei moderni debugger basati su GUI in un pacchetto più leggero e intuitivo. PuDB ti consente di eseguire il debug del codice proprio dove lo scrivi e testalo - in un terminale. Se hai lavorato con gli eccellenti (ma al giorno d'oggi) Turbo Pascal o C basati su DOS, l'interfaccia utente di PuDB potrebbe sembrare familiare.

screenshot di Pudb

Bello per il debug di script autonomi, basta eseguire

python -m pudb.run my-script.py

Installa conpip install pudb
congusbongus il

40

Se si utilizza pdb, è possibile definire alias per le scorciatoie. Io uso questi:

# Ned's .pdbrc

# Print a dictionary, sorted. %1 is the dict, %2 is the prefix for the names.
alias p_ for k in sorted(%1.keys()): print "%s%-15s= %-80.80s" % ("%2",k,repr(%1[k]))

# Print the instance variables of a thing.
alias pi p_ %1.__dict__ %1.

# Print the instance variables of self.
alias ps pi self

# Print the locals.
alias pl p_ locals() local:

# Next and list, and step and list.
alias nl n;;l
alias sl s;;l

# Short cuts for walking up and down the stack
alias uu u;;u
alias uuu u;;u;;u
alias uuuu u;;u;;u;;u
alias uuuuu u;;u;;u;;u;;u
alias dd d;;d
alias ddd d;;d;;d
alias dddd d;;d;;d;;d
alias ddddd d;;d;;d;;d;;d

Come definisci questi alias?
Casebash,

9
Metti questa roba in ~ / .pdbrc
Ned Batchelder il

su Windows puoi inserirlo in ~ / _ipython / ipythonrc.ini
fastmultiplication

33

Registrazione

Python ha già un eccellente modulo di registrazione integrato . Si consiglia di utilizzare il modello di registrazione qui .

Il modulo di registrazione consente di specificare un livello di importanza; durante il debug è possibile registrare tutto, mentre durante il normale funzionamento è possibile registrare solo cose critiche. Puoi spegnere e riaccendere le cose.

Molte persone usano semplicemente le istruzioni di stampa di base per eseguire il debug, quindi rimuovono le istruzioni di stampa. È meglio lasciarli dentro, ma disabilitarli; quindi, quando hai un altro bug, puoi semplicemente riattivare tutto e controllare i tuoi log.

Questo può essere il modo migliore per eseguire il debug di programmi che devono eseguire rapidamente operazioni, ad esempio programmi di rete che devono rispondere prima che l'altra estremità della connessione di rete scada e scompaia. Potresti non avere molto tempo per eseguire un singolo passaggio di un debugger; ma puoi semplicemente lasciare che il tuo codice venga eseguito e registrare tutto, quindi esaminare i registri e capire cosa sta realmente accadendo.

EDIT: l'URL originale per i modelli era: http://aymanh.com/python-debugging-techniques

Manca questa pagina, quindi l'ho sostituita con un riferimento all'istantanea salvata su archive.org: http://web.archive.org/web/20120819135307/http://aymanh.com/python-debugging-techniques

Nel caso in cui scompaia di nuovo, ecco i modelli che ho citato. Questo è il codice preso dal blog; Non l'ho scritto.

import logging
import optparse

LOGGING_LEVELS = {'critical': logging.CRITICAL,
                  'error': logging.ERROR,
                  'warning': logging.WARNING,
                  'info': logging.INFO,
                  'debug': logging.DEBUG}

def main():
  parser = optparse.OptionParser()
  parser.add_option('-l', '--logging-level', help='Logging level')
  parser.add_option('-f', '--logging-file', help='Logging file name')
  (options, args) = parser.parse_args()
  logging_level = LOGGING_LEVELS.get(options.logging_level, logging.NOTSET)
  logging.basicConfig(level=logging_level, filename=options.logging_file,
                      format='%(asctime)s %(levelname)s: %(message)s',
                      datefmt='%Y-%m-%d %H:%M:%S')

  # Your program goes here.
  # You can access command-line arguments using the args variable.

if __name__ == '__main__':
  main()

Ed ecco la sua spiegazione su come usare quanto sopra. Ancora una volta, non ottengo il merito per questo:


Per impostazione predefinita, il modulo di registrazione stampa messaggi critici, di errore e di avviso. Per modificare ciò in modo che tutti i livelli vengano stampati, utilizzare:

$ ./your-program.py --logging=debug

Per inviare messaggi di registro a un file chiamato debug.log, utilizzare:

$ ./your-program.py --logging-level=debug --logging-file=debug.log


1
Il problema con il modulo di registrazione è che si rompe pesantemente con Unicode e sono necessarie varie soluzioni alternative per farlo funzionare all'interno di applicazioni internazionalizzate. Tuttavia, questa è ancora la migliore soluzione di registrazione per Python.
Jacek Konieczny,

Il link "modello di registrazione qui" è morto. Per favore aggiornare.
Yohann,

20

È possibile stampare quali linee Python vengono eseguite (grazie Geo!). Questo ha un numero qualsiasi di applicazioni, ad esempio, è possibile modificarlo per verificare quando vengono chiamate determinate funzioni o aggiungere qualcosa come ## per fare in modo che segua solo determinate righe.

code.interact ti porta in una console interattiva

import code; code.interact(local=locals())

Se vuoi essere in grado di accedere facilmente alla cronologia della tua console, guarda: " Posso avere un meccanismo cronologico come nella shell? " ( Dovrò cercarlo).

Il completamento automatico può essere abilitato per l' interprete .



17

print dichiarazioni

  • Alcune persone raccomandano una debug_printfunzione anziché la stampa per una facile disabilitazione
  • Il pprintmodulo è prezioso per strutture complesse

3
+1 quando ogni debugger fallisce, la stampa è tua amica, sì debug_print sarebbe una bella aggiunta
Anurag Uniyal,

In genere stampo prima, poi eseguo il debug, tranne quando so che sarò in grado di risolvere tracciando una sezione particolare
Casebash,

4
In realtà il modulo di registro fa proprio questo.
e-satis,

Vero, ma è necessario impostare la registrazione. Imparerò come utilizzare il modulo dopo gli onori
Casebash,

la stampa può essere utile per casi semplici e soprattutto quando si sviluppano progetti con tempi di avvio ridotti. D'altra parte può creare dipendenza e usarlo su pdb o qualsiasi altro debugger in scenari più complessi di solito ti causerà mal di testa
vinilios,

16

il modo ovvio di eseguire il debug di una sceneggiatura

python -m pdb script.py
  • utile quando quello script genera un'eccezione
  • utile quando si usano virtualenv e il comando pdb non è in esecuzione con la versione venvs python.

se non sai esattamente dove si trova quello script

python -m pdb ``which <python-script-name>``

15

PyDev

PyDev ha un debugger interattivo abbastanza buono. Ha espressioni di visualizzazione, hover-to-valutare, thread e elenchi di stack e (quasi) tutti i soliti servizi che ti aspetti da un moderno debugger visivo. Puoi persino collegarti a un processo in esecuzione ed eseguire il debug remoto.

Come altri debugger visivi, tuttavia, lo trovo utile soprattutto per problemi semplici o per problemi molto complicati dopo aver provato tutto il resto. Faccio ancora la maggior parte del sollevamento pesante con la registrazione.


Ha la possibilità di modificare e continuare?
Casebash,

@CaseBash no, ma questa funzione è pianificata. Anche senza di esso, tuttavia, la velocità e la facilità di impostazione / disinserimento dei punti di interruzione e la ricerca di valori variabili è ancora molto utile
Jiaaro,


12

Winpdb è molto carino e contrariamente al suo nome è completamente multipiattaforma.

Ha un bel debugger basato su prompt e GUI e supporta il debug remoto.


@Casebash - aggiunti ulteriori dettagli
orip,

1
+1 Questo è l'unico debugger python che ho trovato finora in grado di gestire il multi-threading.
Lee Netherton,

Fai attenzione alla sua "gestione" del multi-threading: qualsiasi eccezione in qualsiasi thread provoca il blocco dell'intero processo. Non è una brutta cosa se ne sei consapevole, molto doloroso se non lo sei
Walt W

Il progetto sembra morto da aprile 2014
Alojz Janez,

7

In Vim, ho questi tre attacchi:

map <F9> Oimport rpdb2; rpdb2.start_embedded_debugger("asdf") #BREAK<esc>
map <F8> Ofrom nose.tools import set_trace; set_trace() #BREAK<esc>
map <F7> Oimport traceback, sys; traceback.print_exception(*sys.exc_info()) #TRACEBACK<esc>

rpdb2è un debugger Python remoto, che può essere utilizzato con WinPDB, un solido debugger grafico. Perché so che lo chiederai, può fare tutto ciò che mi aspetto da un debugger grafico :)

Uso pdbda in nose.toolsmodo da poter eseguire il debug di unit test e codice normale.

Infine, la F7mappatura stamperà un traceback (simile al tipo che si ottiene quando un'eccezione arriva in cima allo stack). L'ho trovato molto utile più di un paio di volte.


4

Definire utili metodi repr () per le classi (in modo da poter vedere cos'è un oggetto) e usare repr () o "% r"% (...) o "... {0! R} ..". (...) nei messaggi / registri di debug è IMHO una chiave per un debug efficiente.

Inoltre, i debugger menzionati in altre risposte useranno i metodi repr ().


2

Ottenere una traccia dello stack da un'applicazione Python in esecuzione

Ci sono molti trucchi qui . Questi includono

  • Entrare in un interprete / stampare una traccia dello stack inviando un segnale
  • Ottenere una traccia dello stack da un processo Python non preparato
  • Esecuzione dell'interprete con flag per renderlo utile per il debug

2

Se non ti piace passare il tempo nei debugger (e non apprezzi la scarsa usabilità dell'interfaccia della pdbriga di comando), puoi scaricare la traccia dell'esecuzione e analizzarla in seguito. Per esempio:

python -m trace -t setup.py install > execution.log

Questo eseguirà il dump di tutta la linea di setup.py installesecuzione sorgente a execution.log.

Per semplificare la personalizzazione dell'output di traccia e la scrittura dei propri traccianti, ho messo insieme alcuni pezzi di codice nel modulo xtrace (dominio pubblico).


1

Quando possibile, eseguo il debug utilizzando M-x pdbin emacs per il debug a livello di sorgente.


1

Esiste un corso online completo chiamato " Software Debugging " di Andreas Zeller su Udacity, ricco di suggerimenti sul debug:

Riepilogo del corso

In questa classe imparerai come eseguire il debug sistematico dei programmi, come automatizzare il processo di debug e creare diversi strumenti di debug automatizzati in Python.

Perché seguire questo corso?

Alla fine di questo corso avrai una solida conoscenza del debug sistematico, saprai come automatizzare il debug e avrai creato diversi strumenti di debug funzionali in Python.

Prerequisiti e requisiti

Sono richieste conoscenze di base di programmazione e Python a livello di Udacity CS101 o superiore. La conoscenza di base della programmazione orientata agli oggetti è utile.

Altamente raccomandato.


0

se vuoi un modo grafico piacevole per stampare il tuo stack di chiamate in modo leggibile, dai un'occhiata a questa utility: https://github.com/joerick/pyinstrument

Esegui dalla riga di comando:

python -m pyinstrument myscript.py [args...]

Esegui come modulo:

from pyinstrument import Profiler

profiler = Profiler()
profiler.start()

# code you want to profile

profiler.stop()
print(profiler.output_text(unicode=True, color=True))

Corri con Django:

Basta aggiungere pyinstrument.middleware.ProfilerMiddlewarea MIDDLEWARE_CLASSES, quindi aggiungere ?profilealla fine dell'URL della richiesta per attivare il profiler.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.