(Mise à jour le 28 mai 2016) Utilisation de RealGUD dans Emacs
Pour tous ceux qui utilisent Emacs, ce fil montre comment accomplir tout ce qui est décrit dans l'OP (et plus encore) en utilisant
- un nouveau débogueur important dans Emacs appelé RealGUD qui peut fonctionner avec n'importe quel débogueur (notamment
ipdb
).
- Le paquet Emacs
isend-mode
.
La combinaison de ces deux paquets est extrêmement puissante et permet de recréer exactement le comportement décrit dans l'OP et de faire encore plus.
Plus d'informations sur l'article de wiki de RealGUD pour ipdb.
Réponse originale :
Après avoir essayé de nombreuses méthodes différentes pour déboguer Python, y compris tout ce qui est mentionné dans ce fil de discussion, l'une de mes méthodes préférées pour déboguer Python avec IPython est l'utilisation de shells intégrés.
Définition d'un shell IPython embarqué personnalisé :
Ajouter ce qui suit sur un script à votre PYTHONPATH
de sorte que la méthode ipsh()
devient disponible.
import inspect
# First import the embed function
from IPython.terminal.embed import InteractiveShellEmbed
from IPython.config.loader import Config
# Configure the prompt so that I know I am in a nested (embedded) shell
cfg = Config()
prompt_config = cfg.PromptManager
prompt_config.in_template = 'N.In <\\#>: '
prompt_config.in2_template = ' .\\D.: '
prompt_config.out_template = 'N.Out<\\#>: '
# Messages displayed when I drop into and exit the shell.
banner_msg = ("\n**Nested Interpreter:\n"
"Hit Ctrl-D to exit interpreter and continue program.\n"
"Note that if you use %kill_embedded, you can fully deactivate\n"
"This embedded instance so it will never turn on again")
exit_msg = '**Leaving Nested interpreter'
# Wrap it in a function that gives me more context:
def ipsh():
ipshell = InteractiveShellEmbed(config=cfg, banner1=banner_msg, exit_msg=exit_msg)
frame = inspect.currentframe().f_back
msg = 'Stopped at {0.f_code.co_filename} at line {0.f_lineno}'.format(frame)
# Go back one level!
# This is needed because the call to ipshell is inside the function ipsh()
ipshell(msg,stack_depth=2)
Ensuite, chaque fois que je veux déboguer quelque chose dans mon code, je place ipsh()
juste à l'endroit où je dois faire l'inspection des objets, etc. Par exemple, disons que je veux déboguer my_function
en dessous de
L'utiliser :
def my_function(b):
a = b
ipsh() # <- This will embed a full-fledged IPython interpreter
a = 4
et ensuite j'invoque my_function(2)
de l'une des manières suivantes :
- Soit en exécutant un programme Python qui invoque cette fonction à partir d'un shell Unix
- Ou en l'invoquant directement depuis IPython
Quelle que soit la façon dont je l'invoque, l'interprète s'arrête à la ligne qui dit ipsh()
. Une fois que vous avez terminé, vous pouvez faire Ctrl-D
et Python reprendra son exécution (avec toutes les mises à jour de variables que vous avez effectuées). Notez que, si vous exécutez le code à partir d'un shell IPython normal (cas 2 ci-dessus), le nouveau shell IPython sera emboîté à l'intérieur de celui à partir duquel vous l'avez invoqué, ce qui est parfaitement normal, mais il est bon d'en être conscient. De toute façon, une fois que l'interpréteur s'arrête sur l'emplacement de ipsh
je peux inspecter la valeur de a
(qui est 2
), voir quelles fonctions et quels objets sont définis, etc.
Le problème :
La solution ci-dessus peut être utilisée pour que Python s'arrête où vous le souhaitez dans votre code, et vous amène ensuite dans un interpréteur IPython à part entière. Malheureusement, elle ne vous permet pas d'ajouter ou de supprimer des points d'arrêt une fois que vous avez invoqué le script, ce qui est très frustrant. À mon avis, c'est le seulement qui empêche IPython de devenir un excellent outil de débogage pour Python.
Le mieux que vous puissiez faire pour le moment :
Une solution de contournement consiste à placer ipsh()
a priori aux différents endroits où vous voulez que l'interpréteur Python lance un shell IPython (c'est-à-dire un breakpoint
). Vous pouvez ensuite "sauter" entre différents "points d'arrêt" prédéfinis et codés en dur avec Ctrl-D
qui quitterait le shell IPython embarqué en cours et s'arrêterait à nouveau dès que l'interpréteur atteindrait le prochain appel à la commande ipsh()
.
Si vous empruntez cette voie, une façon de quitter le "mode de débogage" et d'ignorer tous les points d'arrêt ultérieurs est d'utiliser la commande suivante ipshell.dummy_mode = True
qui fera en sorte que Python ignore toute instanciation ultérieure de l'objet ipshell
que nous avons créé ci-dessus.
0 votes
Pdb a
!
commande qui exécute toute commande python au point d'arrêt5 votes
Je cherche aussi un débogueur python similaire à Matlab ! Par exemple, je fais beaucoup de prototypage dans le shell python. Toutes les variables sont sauvegardées avec le shell. Maintenant je rencontre un problème. J'espère pouvoir déboguer un petit morceau de code, avec ces variables calculées avec le shell. Cependant, un nouveau débogueur ne peut pas accéder aux anciennes variables. Ce n'est pas pratique pour le prototypage.
1 votes
Pour les utilisateurs d'Emacs, RealGUD a une interface incroyablement bonne.
1 votes
Merci @Clément J'ai suivi le dépôt au cours du dernier mois et je suis très enthousiaste à propos du projet :) Je n'ai pas encore essayé, mais quand je l'aurai fait (ou si vous le faites), n'hésitez pas à écrire une réponse ici qui montre peut-être comment accomplir ce qui est demandé. Pour les autres, à titre de référence, l'URL est github.com/rocky/emacs-dbgr
0 votes
@Clément Aussi, si vous avez de l'expérience avec RealGUD & ipdb, j'ai essayé de l'utiliser comme expliqué ici github.com/rocky/emacs-dbgr/issues/96 sans succès.
0 votes
C'est génial que vous ayez ouvert un ticket :) On dirait que votre problème a été résolu, aussi ^^