Quels sont vos meilleurs conseils pour déboguer Python?
S'il vous plaît, ne vous contentez pas de lister un débogueur particulier sans dire ce qu'il peut réellement faire.
Vous pouvez utiliser le module pdb, insérer pdb.set_trace()
n'importe où et il fonctionnera comme un point d'arrêt.
>>> import pdb
>>> a="a string"
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) p a
'a string'
(Pdb)
Pour continuer l'exécution, utilisez c
(ou cont
ou continue
).
Il est possible d'exécuter des expressions Python arbitraires à l'aide de pdb. Par exemple, si vous trouvez une erreur, vous pouvez corriger le code, puis tapez une expression de type pour avoir le même effet dans le code en cours d'exécution.
ipdb est une version de pdb pour IPython . Il permet l'utilisation de pdb avec toutes les fonctionnalités IPython, y compris la complétion par tabulation.
Il est également possible de configurer pdb pour qu'il s'exécute automatiquement sur une exception non interceptée.
Pydb a été écrit pour être une version améliorée de Pdb. Avantages?
http://pypi.python.org/pypi/pudb , un débogueur Python en plein écran et basé sur une console.
Son objectif est de fournir toutes les finesses des débogueurs modernes basés sur une interface graphique dans un package plus léger et convivial pour le clavier. PuDB vous permet de déboguer le code là où vous écrivez et le testez - dans un terminal. Si vous avez travaillé avec les excellents outils Turbo Pascal ou C basés sur DOS (mais qui sont très anciens), l'interface utilisateur de PuDB peut sembler familière.
Idéal pour le débogage de scripts autonomes, il suffit de lancer
python -m pudb.run my-script.py
Si vous utilisez pdb, vous pouvez définir des alias pour les raccourcis. J'utilise ces:
# 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
Journalisation
Python a déjà un excellent module de journalisation intégré . Vous voudrez peut-être utiliser le modèle de journalisation ici .
Le module de journalisation vous permet de spécifier un niveau d'importance. pendant le débogage, vous pouvez tout enregistrer, tandis qu'en fonctionnement normal, vous ne pouvez enregistrer que des choses critiques. Vous pouvez allumer et éteindre les choses.
La plupart des gens utilisent simplement des instructions d'impression de base pour déboguer, puis suppriment les instructions d'impression. Il vaut mieux les laisser dedans, mais les désactiver; ensuite, lorsque vous avez un autre bogue, vous pouvez simplement tout réactiver et consulter vos journaux.
Cela peut constituer le meilleur moyen de déboguer des programmes qui doivent agir rapidement, tels que des programmes réseau devant répondre avant que l’autre extrémité de la connexion réseau n’expire et ne disparaisse. Vous n’avez peut-être pas beaucoup de temps pour déboguer en une seule étape; mais vous pouvez simplement laisser votre code s'exécuter et tout journaliser, puis parcourir les journaux et comprendre ce qui se passe réellement.
EDIT: L'URL d'origine des modèles était: http://aymanh.com/python-debugging-techniques
Cette page est manquante alors je l'ai remplacée par une référence à l'instantané enregistré sur archive.org: http://web.archive.org/web/20120819135307/http://aymanh.com/python-debugging- techniques
Au cas où il disparaîtrait encore, voici les modèles que j'ai mentionnés. C'est du code tiré du blog; Je ne l'ai pas écrit.
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 __== '__main__':
main()
Et voici son explication sur la façon d'utiliser ce qui précède. Encore une fois, je ne reçois pas le crédit pour cela:
Par défaut, le module de journalisation imprime des messages critiques, d'erreur et d'avertissement. Pour changer ceci afin que tous les niveaux soient imprimés, utilisez:
$ ./your-program.py --logging=debug
Pour envoyer des messages de journal à un fichier appelé debug.log, utilisez:
$ ./your-program.py --logging-level=debug --logging-file=debug.log
Il est possible d’imprimer quoi les lignes Python sont exécutées (merci Geo!). Cela a un nombre quelconque d'applications, par exemple, vous pouvez le modifier pour vérifier le moment où des fonctions particulières sont appelées ou ajouter quelque chose comme ## le faire suivre uniquement des lignes particulières.
code.interact vous emmène dans une console interactive
import code; code.interact(local=locals())
Si vous voulez pouvoir accéder facilement à l’historique de votre console, regardez: " Puis-je avoir un mécanisme d’historique comme dans le shell? " (il faudra le chercher).
La saisie automatique peut être activée pour le interprète .
ipdb est comme pdb, avec le génie d'Ipython.
print
déclarations
debug_print
au lieu d’imprimer pour la désactiver facilement.pprint
est inestimable pour les structures complexesle moyen évident de déboguer un script
python -m pdb script.py
si vous ne savez pas exactement où se trouve ce script
python -m pdb ``which <python-script-name>``
PyDev
PyDev a un très bon débogueur interactif. Il contient des expressions de regard, des survols en amont, des listes de threads et de piles et (presque) toutes les commodités habituelles que vous attendez d'un débogueur visuel moderne. Vous pouvez même vous connecter à un processus en cours et effectuer un débogage à distance.
Cependant, à l'instar d'autres débogueurs visuels, je le trouve utile principalement pour des problèmes simples ou pour des problèmes très compliqués après avoir essayé tout le reste. Je fais toujours l'essentiel du travail lourd avec l'exploitation forestière.
Si vous connaissez Visual Studio, Outils Python pour Visual Studio est ce que vous recherchez.
Winpdb est très gentil, et contrairement à son nom, il est complètement multi-plateforme.
Il possède un très bon débogueur d'interface graphique et basé sur une invite, et prend en charge le débogage à distance.
Dans Vim, j'ai ces trois liaisons:
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
est un débogueur distant Python pouvant être utilisé avec WinPDB, un débogueur graphique plein. Parce que je sais que vous allez demander, il peut faire tout ce que je m'attends d'un débogueur graphique :)
J'utilise pdb
à partir de nose.tools
pour pouvoir déboguer des tests unitaires ainsi que du code normal.
Enfin, le mappage F7
imprimera une trace (semblable à celle que vous obtenez lorsqu'une exception survient en haut de la pile). Je l'ai trouvé très utile plusieurs fois.
Définir des méthodes utiles repr () pour vos classes (afin que vous puissiez voir ce qu’est un objet) et utiliser repr () ou "% r"% (...) ou "... {0! r} .. ". Le format (...) dans vos messages/journaux de débogage est, à mon humble avis, un élément clé pour un débogage efficace.
De plus, les débogueurs mentionnés dans d'autres réponses utiliseront les méthodes repr ().
Obtention d'une trace de pile à partir d'une application Python en cours d'exécution
Il y a plusieurs astuces ici . Ceux-ci inclus
Si vous n'aimez pas passer du temps dans les débogueurs (et n'appréciez pas la mauvaise utilisation de l'interface de ligne de commande pdb
), vous pouvez vider l'exécution trace et l'analyser ultérieurement. Par exemple:
python -m trace -t setup.py install > execution.log
Cela va vider toute la ligne source de setup.py install
exécution en execution.log
.
Pour faciliter la personnalisation de la sortie de trace et l'écriture de vos propres traceurs, j'ai rassemblé quelques éléments de code dans le module xtrace (domaine public).
Il existe un cours en ligne complet intitulé " Débogage logiciel " par Andreas Zeller sur Udacity, qui regorge de conseils sur le débogage:
Résumé du cours
Dans cette classe, vous apprendrez à déboguer des programmes de manière systématique, à automatiser le processus de débogage et à construire plusieurs outils de débogage automatisés en Python.
Pourquoi suivre ce cours?
À la fin de ce cours, vous aurez une solide connaissance du débogage systématique, vous saurez comment automatiser le débogage et vous aurez construit plusieurs outils de débogage fonctionnels en Python.
Conditions préalables et exigences
Des connaissances de base en programmation et en Python au niveau de Udacity CS101 ou supérieur sont requises. Compréhension de base de la programmation orientée objet est utile.
Hautement recommandé.
Lorsque cela est possible, je débogue en utilisant M-x pdb
dans emacs pour le débogage au niveau source.
si vous voulez un moyen graphique agréable d’imprimer votre pile d’appels de manière lisible, consultez cet utilitaire: https://github.com/joerick/pyinstrument
Exécuter en ligne de commande:
python -m pyinstrument myscript.py [args...]
Exécuter en tant que module:
from pyinstrument import Profiler
profiler = Profiler()
profiler.start()
# code you want to profile
profiler.stop()
print(profiler.output_text(unicode=True, color=True))
Courir avec Django:
Ajoutez simplement pyinstrument.middleware.ProfilerMiddleware
à MIDDLEWARE_CLASSES
, puis ajoutez ?profile
à la fin de l'URL de la demande pour activer le profileur.