web-dev-qa-db-fra.com

Comment déboguer dans Django, le bon chemin?

J'ai donc commencé à apprendre à coder dans Python et plus tard Django . Les premières fois, il était difficile de regarder les retraits et de comprendre ce que j’avais mal fait et où se trouvait l’erreur de syntaxe. Un peu de temps s’est écoulé et un peu plus loin, je suppose que j’ai une routine pour déboguer mon code Django. Comme cela a été fait au début de mon expérience de codage, je me suis assis et je me suis demandé si cela était inefficace et pouvait être fait plus rapidement. Je parviens généralement à trouver et à corriger les bugs dans mon code, mais je me demande si je devrais le faire plus rapidement?

D'habitude, j'utilise simplement les informations de débogage que Django donne lorsqu'il est activé. Lorsque les choses finissent comme je le pensais, je casse beaucoup le flux de code avec une erreur de syntaxe et je regarde les variables à cet endroit du flux pour déterminer si le code fait autre chose que ce que je voulais.

Mais cela peut-il être amélioré? Existe-t-il de bons outils ou de meilleurs moyens de déboguer votre code Django?

517
googletorp

Il existe de nombreuses façons de le faire, mais la plus simple consiste à simplement utiliser Le le débogueur Python . Ajoutez simplement la ligne suivante à une fonction de vue Django:

import pdb; pdb.set_trace()

Si vous essayez de charger cette page dans votre navigateur, celui-ci se bloque et vous recevez une invite à poursuivre le débogage du code en cours d'exécution.

Cependant, il existe d'autres options (je ne les recommande pas):

* return HttpResponse({variable to inspect})

* print {variable to inspect}

* raise Exception({variable to inspect})

Mais le débogueur Python (pdb) est fortement recommandé pour tous les types de code Python. Si vous êtes déjà dans pdb, vous devriez également jeter un coup d'œil à IPDB qui utilise ipython pour le débogage.

Quelques extensions plus utiles à pdb sont

pdb ++ , suggéré par Antash .

pudb , suggéré par PatDuJour .

Utilisation du débogueur Python dans Django , suggéré par Seafangs .

482
simplyharsh

J'aime beaucoup le débogueur interactif de Werkzeug . C'est semblable à la page de débogage de Django, sauf que vous obtenez un shell interactif à chaque niveau de la trace. Si vous utilisez Django-extensions , vous obtenez une commande runserver_plus qui lance le serveur de développement et vous fournit le débogueur de Werkzeug sur les exceptions.

Bien sûr, vous ne devriez l'exécuter que localement, car cela donne à toute personne disposant d'un navigateur le droit d'exécuter du code python arbitraire dans le contexte du serveur.

219
Benjamin Wohlwend

Un petit coup rapide pour les balises de modèle:

@register.filter 
def pdb(element):
    import pdb; pdb.set_trace()
    return element

Maintenant, dans un modèle, vous pouvez créer {{ template_var|pdb }} et entrer une session pdb (étant donné que vous exécutez le serveur de développement local) où vous pouvez inspecter element au contenu de votre coeur.

C'est un moyen très agréable de voir ce qui est arrivé à votre objet lorsqu'il arrive au modèle. 

155
Koobz

Quelques outils coopèrent bien et peuvent faciliter votre tâche de débogage.

Le plus important est la barre d’outils de débogage Django .

Ensuite, vous avez besoin d’une bonne journalisation à l’aide de l’utilitaire Python logging . Vous pouvez envoyer la sortie de journalisation dans un fichier journal, mais une option plus simple consiste à envoyer la sortie du journal à firepython . Pour utiliser cela, vous devez utiliser le navigateur Firefox avec l'extension firebug . Firepython inclut un plugin Firebug qui affiche toute journalisation côté serveur dans un onglet Firebug.

Firebug lui-même est également essentiel pour le débogage du côté Javascript de toute application que vous développez. (En supposant que vous ayez un code JS bien sûr).

J'ai aussi aimé Django-viewtools pour le débogage interactif de vues utilisant pdb, mais je ne l'utilise pas beaucoup.

Il existe d'autres outils utiles tels que dozer pour localiser les fuites de mémoire (il existe également d'autres suggestions utiles données dans les réponses ici sur SO pour le suivi de mémoire).

80
Van Gale

J'utilise PyCharm (même moteur pydev qu'Eclipse). M'aide réellement à visualiser le code et à voir ce qui se passe.

54
PhoebeB

Presque tout a été mentionné jusqu'à présent. J'ajouterai donc qu'au lieu de pdb.set_trace(), vous pouvez utiliser ipdb.set_trace () , qui utilise iPython et est donc plus puissant (saisie automatique et autres goodies). Cela nécessite le paquet ipdb, il vous suffit donc de pip install ipdb

41
Tomasz Zielinski

J'ai poussé Django-pdb vers PyPI . C'est une application simple qui signifie que vous n'avez pas besoin de modifier votre code source à chaque fois que vous souhaitez entrer dans pdb.

L'installation est juste ...

  1. pip install Django-pdb
  2. Ajoutez 'Django_pdb' à votre INSTALLED_APPS

Vous pouvez maintenant lancer: manage.py runserver --pdb pour entrer dans pdb au début de chaque vue ...

bash: manage.py runserver --pdb
Validating models...

0 errors found
Django version 1.3, using settings 'testproject.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

GET /
function "myview" in testapp/views.py:6
args: ()
kwargs: {}

> /Users/tom/github/Django-pdb/testproject/testapp/views.py(7)myview()
-> a = 1
(Pdb)

Et lancez: manage.py test --pdb pour entrer dans pdb en cas d'échec/d'erreur de test ...

bash: manage.py test testapp --pdb
Creating test database for alias 'default'...
E
======================================================================
>>> test_error (testapp.tests.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../Django-pdb/testproject/testapp/tests.py", line 16, in test_error
    one_plus_one = four
NameError: global name 'four' is not defined
======================================================================

> /Users/tom/github/Django-pdb/testproject/testapp/tests.py(16)test_error()
-> one_plus_one = four
(Pdb)

Le projet est hébergé sur GitHub , les contributions sont évidemment les bienvenues.

32
Tom Christie

Le moyen le plus simple de déboguer python - en particulier pour les programmeurs habitués à Visual Studio - utilise PTVS (Python Tools for Visual Studio). Les étapes sont simples: 

  1. Téléchargez-le et installez-le à partir de http://pytools.codeplex.com/
  2. Définissez les points d'arrêt et appuyez sur F5. 
  3. Votre point d'arrêt étant atteint, vous pouvez visualiser/modifier les variables aussi facilement que le débogage de programmes C #/C++. 
  4. C'est tout :) 

Si vous souhaitez déboguer Django à l'aide de PTVS, procédez comme suit: 

  1. Dans les paramètres du projet - onglet Général, définissez "Fichier de démarrage" sur "manage.py", le point d'entrée du programme Django. 
  2. Dans les paramètres du projet - onglet Débogage, définissez "Arguments de script" sur "runserver --noreload". Le point clé est le "--noreload" ici. Si vous ne le définissez pas, vos points d'arrêt ne seront pas touchés. 
  3. Profitez-en.
20
029xue

J'utilise pyDev avec Eclipse vraiment bien, définit des points de rupture, passe au code, visualise les valeurs de tous les objets et variables, essayez-le.

15
gath

J'utilise PyCharm et je le respecte jusqu'au bout. Cela m'a coûté un peu, mais je dois dire que l'avantage que j'en retire est inestimable. J'ai essayé le débogage depuis la console et je donne beaucoup de crédit aux gens qui peuvent le faire, mais pour moi, pouvoir déboguer visuellement mes applications est génial.

Je dois dire cependant que PyCharm prend beaucoup de mémoire. Mais là encore, rien de bon n’est gratuit dans la vie. Ils viennent juste de sortir leur dernière version 3. Cela fonctionne également très bien avec Django, Flask et Google AppEngine. Donc, dans l’ensemble, je dirais que c’est un excellent outil pratique pour tout développeur.

Si vous ne l'utilisez pas encore, je vous conseillerais de vous procurer la version d'évaluation pendant 30 jours afin de jeter un coup d'œil à la puissance de PyCharm. Je suis sûr qu'il existe d'autres outils également disponibles, tels qu'Aptana. Mais je suppose que j'aime aussi tout à fait l'apparence de PyCharm. Je me sens très à l'aise pour déboguer mes applications là-bas.

10
Khan

De mon point de vue, nous pourrions décomposer les tâches de débogage de code courantes en trois modèles d'utilisation distincts:

  1. Quelque chose a levé une exception: runserver_plus 'Le débogueur de Werkzeug à la rescousse. La possibilité d'exécuter du code personnalisé à tous les niveaux de trace est un tueur. Et si vous êtes complètement bloqué, vous pouvez créer un Gist à partager en un clic.
  2. La page est rendue, mais le résultat est faux: encore une fois, Werkzeug bascule. Pour créer un point d'arrêt dans le code, tapez simplement assert False à l'endroit où vous souhaitez vous arrêter.
  3. Le code fonctionne mal, mais le coup d’œil rapide n’aide en rien. Très probablement, un problème algorithmique. Soupir. Ensuite, je lance habituellement un débogueur de console PuDB : import pudb; pudb.set_trace(). Le principal avantage de [i] pdb est que PuDB (tout en regardant dans les années 80) facilite grandement la définition d’expressions de surveillance personnalisées. Et le débogage d'un tas de boucles imbriquées est beaucoup plus simple avec une interface graphique.

Ah oui, les malheurs des templates. Le problème le plus courant (pour moi et mes collègues) est un contexte erroné: vous n'avez pas de variable ou votre variable n'a pas d'attribut. Si vous utilisez debug toolbar , inspectez simplement le contexte dans la section "Modèles" ou, si cela ne suffit pas, définissez une rupture dans le code de vos vues juste après que votre contexte soit rempli.

Alors ça va.

9
Alex Morozov

Parfois, lorsque je souhaite explorer une méthode particulière et que la convocation de pdb est trop lourde, je voudrais ajouter:

import IPython; IPython.embed()

IPython.embed() démarre un shell IPython qui a accès aux variables locales à partir du point où vous l'appelez. 

8
Lie Ryan

Je viens de trouver wdb ( http://www.rkblog.rk.edu.pl/w/p/debugging-python-code-browser-wdb-debugger/?goback=%2Egde_25827_member_255996401 ). Il a une belle interface utilisateur/interface graphique avec tous les cloches et les sifflets. L'auteur dit ceci à propos de wdb -

"Il existe des IDE comme PyCharm qui ont leurs propres débogueurs. Ils offrent un ensemble similaire ou égal de fonctionnalités ... Cependant, pour les utiliser, vous devez utiliser ces IDE spécifiques (et certains d'entre eux sont alors non libres ou peuvent ne pas être disponibles pour tous. Choisissez le bon outil pour vos besoins. "

Je pensais juste le passer.

Également un article très utile sur les débogueurs Python:https://zapier.com/engineering/debugging-python-boss/

Enfin, si vous souhaitez voir une impression graphique de Nice de votre pile d’appels dans Django, procédez à la commande suivante: https://github.com/joerick/pyinstrument . Ajoutez simplement pyinstrument.middleware.ProfilerMiddleware à MIDDLEWARE_CLASSES, puis ajoutez? Profile à la fin de l'URL de la demande pour activer le profileur. 

Peut également exécuter pyinstrument à partir de la ligne de commande ou en l'important en tant que module.

6
Hutch

Je recommande fortement epdb (débogueur Python étendu). 

https://bitbucket.org/dugan/epdb

Une des choses que j'aime chez epdb pour le débogage de Django ou d'autres serveurs Web Python est la commande epdb.serve (). Cela définit une trace et la sert sur un port local auquel vous pouvez vous connecter. Cas d'utilisation typique:

J'ai un point de vue que je veux parcourir étape par étape. Je vais insérer le texte suivant au moment où je souhaite définir la trace.

import epdb; epdb.serve()

Une fois ce code exécuté, j'ouvre un interpréteur Python et me connecte à l'instance serveur. Je peux analyser toutes les valeurs et parcourir le code à l'aide des commandes pdb standard telles que n, s, etc.

In [2]: import epdb; epdb.connect()
(Epdb) request
<WSGIRequest
path:/foo,
GET:<QueryDict: {}>, 
POST:<QuestDict: {}>,
...
>
(Epdb) request.session.session_key
'i31kq7lljj3up5v7hbw9cff0rga2vlq5'
(Epdb) list
 85         raise some_error.CustomError()
 86 
 87     # Example login view
 88     def login(request, username, password):
 89         import epdb; epdb.serve()
 90  ->     return my_login_method(username, password)
 91
 92     # Example view to show session key
 93     def get_session_key(request):
 94         return request.session.session_key
 95

Et beaucoup plus que vous pouvez en apprendre davantage sur la saisie d’aide epdb à tout moment.

Si vous souhaitez servir ou vous connecter à plusieurs instances epdb simultanément, vous pouvez spécifier le port d'écoute (le port par défaut est 8080). C'est à dire.

import epdb; epdb.serve(4242)

>> import epdb; epdb.connect(Host='192.168.3.2', port=4242)

L'hôte par défaut est 'localhost' s'il n'est pas spécifié. Je l'ai jeté ici pour montrer comment vous pouvez l'utiliser pour déboguer quelque chose d'autre qu'une instance locale, comme un serveur de développement sur votre réseau local. Évidemment, si vous faites cela, veillez à ce que la trace définie ne parvienne jamais sur votre serveur de production!

Pour résumer, vous pouvez toujours faire la même chose que la réponse acceptée avec epdb (import epdb; epdb.set_trace()), mais je voulais mettre en évidence la fonctionnalité serve car je l’ai trouvée très utile.

6
Jacinda

J'utilise PyCharm et différents outils de débogage. Également avoir un Nice articles mis sur facile configurer ces choses pour les novices. Vous pouvez commencer ici. Il parle du débogage de la PDB et de l'interface graphique en général avec les projets Django. J'espère que quelqu'un en profiterait.

3
garmoncheg

Ajoutez import pdb; pdb.set_trace() à la ligne correspondante dans le code Python et exécutez-le. L'exécution s'arrêtera avec un shell interactif. Dans le shell, vous pouvez exécuter du code Python (c’est-à-dire des variables d’impression) ou utiliser des commandes telles que:

  • c continuer l'exécution
  • n passer à la ligne suivante dans la même fonction
  • s passer à la ligne suivante de cette fonction ou à une fonction appelée
  • q quitter le débogueur/exécution

Voir aussi: https://poweruser.blog/setting-a-breakpoint-in-python-438e23fe6b28

2
Chris

Si vous utilisez Aptana pour le développement Django, regardez ceci: http://www.youtube.com/watch?v=qQh-UQFltJQ

Sinon, envisagez de l'utiliser.

2
user1144616

Pour ceux qui peuvent ajouter accidentellement pdb à des commits en direct, je peux suggérer cette extension de la réponse #Koobz:

@register.filter 
def pdb(element):
    from Django.conf import settings
    if settings.DEBUG:    
        import pdb
        pdb.set_trace()
    return element
2
MontyThreeCard

La plupart des options sont déjà mentionnées. Pour imprimer un contexte de modèle, j'ai créé une bibliothèque simple pour cela ... Voir https://github.com/edoburu/Django-debugtools

Vous pouvez l'utiliser pour imprimer le contexte d'un modèle sans construction {% load %}:

{% print var %}   prints variable
{% print %}       prints all

Il utilise un format pprint personnalisé pour afficher les variables dans une balise <pre>.

2
vdboor

Je trouve que Visual Studio Code est génial pour le débogage des applications Django. Les paramètres standard python launch.json exécutent python manage.py avec le débogueur attaché afin que vous puissiez définir des points d'arrêt et parcourir votre code à votre guise.

2
Noah MacCallum

Une des meilleures options pour déboguer le code Django est via wdb: https://github.com/Kozea/wdb

wdb fonctionne avec python 2 (2.6, 2.7), python 3 (3.2, 3.3, 3.4, 3.5) et pypy. Mieux encore, il est possible de déboguer un programme python 2 avec un serveur wdb s'exécutant sur python 3 et inversement ou de déboguer un programme s'exécutant sur un ordinateur avec un serveur de débogage exécuté sur un autre ordinateur dans une page Web d'un troisième ordinateur! __. Encore mieux, il est maintenant possible de suspendre un processus/thread en cours de python en utilisant l’injection de code à partir de l’interface Web. (Cela nécessite que gdb et ptrace soient activés) En d’autres termes, c’est une version très améliorée de pdb directement dans votre navigateur avec les fonctionnalités de Nice.

Installez et exécutez le serveur et ajoutez dans votre code:

import wdb
wdb.set_trace()

Selon l'auteur, les principales différences par rapport à pdb sont les suivantes:

Pour ceux qui ne connaissent pas le projet, wdb est un débogueur python comme pdb, mais avec un front web lisse et de nombreuses fonctionnalités supplémentaires, telles que:

  • Mise en évidence de la syntaxe source 
  • Points d'arrêt visuels 
  • Achèvement du code interactif avec Jedi 
  • Points d'arrêt persistants 
  • Inspection approfondie d'objets à l'aide de la souris Prise en charge du multithreading/multitraitement
  • Débogage à distance
  • Regarder les expressions 
  • Dans l'édition du code du débogueur 
  • Intégration de serveurs Web populaires à rompre en cas d'erreur 
  • En exception, rupture au cours de la trace (pas post-mortem) contrairement au débogueur de werkzeug par exemple
  • Interruption des programmes en cours d'exécution via l'injection de code (sur les systèmes pris en charge)

Il a une excellente interface utilisateur basée sur un navigateur. Une joie à utiliser! :)

2
fessacchiotto

je suggère fortement d'utiliser PDB.

import pdb
pdb.set_trace()

Vous pouvez inspecter toutes les valeurs des variables, entrer dans la fonction et bien plus encore . https://docs.python.org/2/library/pdb.html

pour vérifier tous les types de demandes, réponses et hits de la base de données. J'utilise Django-debug-toolbar https://github.com/Django-debug-toolbar/Django-debug-toolbar

1
nitansh bareja

Comme mentionné dans d'autres articles ici - définir des points d'arrêt dans votre code et parcourir le code pour voir s'il se comporte comme prévu était un excellent moyen d'apprendre quelque chose comme Django jusqu'à ce que vous sachiez comment tout cela se comporte - et quel est votre code. fait.

Pour ce faire, je recommanderais d'utiliser WingIde. Tout comme les autres IDE mentionnés, Nice et facile à utiliser, Nice layout et également facile à définir des points d'arrêt évaluent/modifient la pile, etc. Parfait pour visualiser ce que votre code est en train de faire défiler. Je suis un grand fan de ça.

J'utilise aussi PyCharm - il a une excellente analyse de code statique et peut parfois aider à déceler les problèmes avant de réaliser qu'ils existent.

Comme déjà mentionné, Django-debug-toolbar est essentiel - https://github.com/Django-debug-toolbar/Django-debug-toolbar

Et bien qu’il ne s’agisse pas explicitement d’un outil de débogage ou d’analyse - l’un de mes favoris est SQL Printing Middleware disponible auprès de Django Snippets à l’adresse https://djangosnippets.org/snippets/290/

Cela affichera les requêtes SQL générées par votre vue. Cela vous donnera une bonne idée de ce que fait l'ORM et vous indique si vos requêtes sont efficaces ou si vous devez retravailler votre code (ou ajouter de la mise en cache).

Je le trouve très utile pour surveiller les performances des requêtes lors du développement et du débogage de mon application. 

Juste un autre conseil - je l’ai légèrement modifié pour mon usage personnel afin d’afficher uniquement le résumé, et non l’instruction SQL ... Je l’utilise donc toujours lors du développement et des tests. J'ai également ajouté que si le len (connection.queries) est supérieur à un seuil prédéfini, il affiche un avertissement supplémentaire.

Ensuite, si quelque chose de mauvais se produit (du point de vue des performances ou du nombre de requêtes), je reviens à l'affichage complet des instructions SQL pour voir exactement ce qui se passe. Très pratique lorsque vous travaillez sur un grand projet Django avec plusieurs développeurs.

1
IanH

Pendant le développement, ajouter un rapide

assert False, value

peut vous aider à diagnostiquer des problèmes dans des vues ou ailleurs, sans avoir besoin d'un débogueur.

0
Udi

Une suggestion supplémentaire. 

Vous pouvez utiliser nosetests et pdb ensemble, plutôt que d’injecter pdb.set_trace() dans vos vues manuellement. L'avantage est que vous pouvez observer les conditions d'erreur lors de leur premier démarrage, potentiellement dans du code tiers.

Voici une erreur pour moi aujourd'hui.

TypeError at /db/hcm91dmo/catalog/records/

render_option() argument after * must be a sequence, not int

....


Error during template rendering

In template /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/crispy_forms/templates/bootstrap3/field.html, error at line 28
render_option() argument after * must be a sequence, not int
18  
19          {% if field|is_checkboxselectmultiple %}
20              {% include 'bootstrap3/layout/checkboxselectmultiple.html' %}
21          {% endif %}
22  
23          {% if field|is_radioselect %}
24              {% include 'bootstrap3/layout/radioselect.html' %}
25          {% endif %}
26  
27          {% if not field|is_checkboxselectmultiple and not field|is_radioselect %}
28  

      {% if field|is_checkbox and form_show_labels %}

Maintenant, je sais que cela signifie que j'ai gaffé le constructeur pour la forme, et j'ai même une bonne idée de quel domaine est un problème. Mais, puis-je utiliser pdb pour voir quelles sont les formes croustillantes qui se plaignent, dans un modèle ?

Oui je peux. Utilisation de l’option --pdb sur nos nosetest:

tests$ nosetests test_urls_catalog.py --pdb

Dès que je frappe une exception (y compris celles gérées avec élégance), pdb s'arrête là où cela se produit et je peux regarder autour de moi.

  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django/forms/forms.py", line 537, in __str__
    return self.as_widget()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django/forms/forms.py", line 593, in as_widget
    return force_text(widget.render(name, self.value(), attrs=attrs))
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django/forms/widgets.py", line 513, in render
    options = self.render_options(choices, [value])
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django/forms/widgets.py", line 543, in render_options
    output.append(self.render_option(selected_choices, *option))
TypeError: render_option() argument after * must be a sequence, not int
INFO lib.capture_middleware log write_to_index(http://localhost:8082/db/hcm91dmo/catalog/records.html)
INFO lib.capture_middleware log write_to_index:end
> /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django/forms/widgets.py(543)render_options()
-> output.append(self.render_option(selected_choices, *option))
(Pdb) import pprint
(Pdb) pprint.PrettyPrinter(indent=4).pprint(self)
<Django.forms.widgets.Select object at 0x115fe7d10>
(Pdb) pprint.PrettyPrinter(indent=4).pprint(vars(self))
{   'attrs': {   'class': 'select form-control'},
    'choices': [[('_', 'any type'), (7, (7, 'type 7', 'RECTYPE_TABLE'))]],
    'is_required': False}
(Pdb)         

Maintenant, il est clair que mon argument de choix au constructeur de champs croustillants était comme s'il s'agissait d'une liste dans une liste plutôt que d'une liste/d'un nuplet de tuples.

 'choices': [[('_', 'any type'), (7, (7, 'type 7', 'RECTYPE_TABLE'))]]

La chose intéressante est que cette base de données se déroule dans le code de Crispy, pas le mien et je n'ai pas eu besoin de l'insérer manuellement.

0
JL Peyret

utilisez pdb ou ipdb. La différence entre ces deux solutions est que ipdb prend en charge la saisie automatique.

pour pdb

import pdb
pdb.set_trace()

pour ipdb

import ipdb
ipdb.set_trace()

Pour exécuter une nouvelle ligne, appuyez sur la touche n, pour continuer, appuyez sur la touche c ., Vérifiez davantage d'options en utilisant help(pdb).

0
Abdul Gaffar