J'ai copié le code Ruby suivant à partir d'Internet et j'ai apporté quelques modifications mais cela ne fonctionne pas.
Que puis-je faire pour déboguer le programme moi-même?
J'ai copié le code Ruby suivant à partir d'Internet et j'ai apporté quelques modifications mais cela ne fonctionne pas.
Que puis-je faire pour déboguer le programme moi-même?
Réponses:
Installer via:
$ gem install pry
$ pry
Puis ajouter:
require 'pry'; binding.pry
dans votre programme.
A partir de pry
0.12.2 cependant, il n'y a pas de commandes de navigation telles que next
, break
etc. Quelques autres pierres précieuses offrent en outre cela, voir par exemple pry-byedebug
.
binding.pry
. Il est également livré avec l'achèvement des couleurs, la recherche de documentation et la possibilité d'éditer et de recharger dynamiquement une méthode.
Pry
/ byebug
sont excellents, mais pas comme votre première étape lors du débogage. Dans la plupart des cas, lever une exception avec raise object.inspect
résoudra votre problème plus rapidement que d'ouvrir une session irb. Je recommande de n'utiliser les débogueurs de la console qu'une fois de plus, des solutions simples comme lever une exception ne peuvent pas résoudre votre problème.
pry
? Je n'ai pas pu trouver comment faire; et c'est ce que j'attends d'un débogueur.
En rubis:
ruby -rdebug myscript.rb
puis,
b <line>
: mettre le point de rupture n(ext)
ou s(tep)
etc(ontinue)
p(uts)
pour l'affichage(comme le débogage perl)
In Rails: lancez le serveur avec
script/server --debugger
et ajoutez debugger
le code.
-r debug
sont des déchets?
facets
exigences de la gemme, et j'ai échoué. Pour les anciennes applications Rails, ruby-debug
c'est un peu méchant, mais fait le travail.
Comme la rampe recommandée: utilisez le levier! Je ne peux qu'être d'accord là-dessus.
pry est une bien meilleure réplique que irb.
Vous devez ajouter
require 'pry'
à votre fichier source, puis insérez un point d'arrêt dans votre code source en ajoutant
binding.pry
à l'endroit où vous souhaitez voir les choses (c'est comme déclencher un point d'arrêt dans un environnement IDE classique)
Une fois que votre programme atteint le
binding.pry
line, vous serez jeté directement dans le pry repl, avec tout le contexte de votre programme à portée de main, de sorte que vous puissiez simplement tout explorer, enquêter sur tous les objets, changer d'état et même changer le code à la volée.
Je crois que vous ne pouvez pas changer le code de la méthode dans laquelle vous êtes actuellement, donc vous ne pouvez malheureusement pas changer la ligne suivante à exécuter. Mais un bon code ruby a tendance à être une seule ligne de toute façon ;-)
Le débogage en levant des exceptions est beaucoup plus facile que de plisser les yeux dansprint
les instructions de journal, et pour la plupart des bogues, c'est généralement beaucoup plus rapide que d'ouvrir un débogueur irb commepry
oubyebug
. Ces outils ne devraient pas toujours être votre première étape.
Exception
alors et.inspect
son résultatLe moyen le plus rapide de déboguer du code Ruby (en particulier Rails) consiste à faire raise
une exception le long du chemin d'exécution de votre code lors de l'appel .inspect
de la méthode ou de l'objet (par exemple foo
):
raise foo.inspect
Dans le code ci-dessus, raise
déclenche un Exception
qui interrompt l'exécution de votre code et renvoie un message d'erreur contenant des .inspect
informations sur l'objet / la méthode (c.-à-d.foo
) sur la ligne que vous essayez de déboguer.
Cette technique est utile pour examiner rapidement un objet ou une méthode ( par exemple nil
? ) Et pour confirmer immédiatement si une ligne de code est même exécutée dans un contexte donné.
byebug
oupry
Ce n'est qu'après avoir obtenu des informations sur l'état de votre flux d'exécution de codes que vous devriez envisager de passer à un débogueur ruby gem irb comme pry
ou byebug
où vous pouvez approfondir l'état des objets dans votre chemin d'exécution.
Lorsque vous essayez de déboguer un problème, nous vous conseillons de toujours: Lire le message d'erreur! @ # $ Ing (RTFM)
Cela signifie lire attentivement et complètement les messages d'erreur avant d'agir afin de comprendre ce qu'il essaie de vous dire. Lorsque vous déboguez, posez les questions mentales suivantes, dans cet ordre , lors de la lecture d'un message d'erreur:
nil
? ) Dans la trace de pile, portez une attention particulière aux lignes de code qui proviennent de votre projet (par exemple, les lignes commençant par app/...
si vous utilisez Rails). 99% du temps, le problème vient de votre propre code.
Pour illustrer pourquoi interpréter dans cet ordre est important d' ...
Vous exécutez du code qui à un moment donné s'exécute comme tel:
@foo = Foo.new
...
@foo.bar
et vous obtenez une erreur indiquant:
undefined method "bar" for Nil:nilClass
Les débutants voient cette erreur et pensent que le problème est que la méthode bar
n'est pas définie . Ce n'est pas. Dans cette erreur, la vraie partie qui compte est:
for Nil:nilClass
for Nil:nilClass
signifie que @foo
c'est nul! @foo
n'est pas une Foo
variable d'instance! Vous avez un objet qui l'est Nil
. Lorsque vous voyez cette erreur, c'est simplement ruby qui essaie de vous dire que la méthode bar
n'existe pas pour les objets de la classe Nil
. (enfin duh! puisque nous essayons d'utiliser une méthode pour un objet de la classe Foo
non Nil
).
Malheureusement, en raison de la façon dont cette erreur est écrite ( undefined method "bar" for Nil:nilClass
), il est facile de se faire tromper en pensant que cette erreur a à voir avec l' bar
être undefined
. Lorsqu'elle n'est pas lue attentivement, cette erreur amène les débutants à creuser par erreur les détails de la bar
méthode surFoo
, manquant entièrement la partie de l'erreur qui indique que l'objet est de la mauvaise classe (dans ce cas: nil). C'est une erreur qui est facilement évitée en lisant les messages d'erreur dans leur intégralité.
Résumé:
Lisez toujours attentivement l' intégralité du message d'erreur avant de commencer tout débogage. Cela signifie: vérifiez toujours le type de classe d'un objet dans un message d'erreur d' abord , puis ses méthodes , avant de commencer à fouiller dans une trace de pile ou une ligne de code où vous pensez que l'erreur peut se produire. Ces 5 secondes peuvent vous épargner 5 heures de frustration.
tl; dr: Ne pas plisser les yeux sur les journaux d'impression: lever des exceptions ou utiliser un débogueur irb à la place. Évitez les terriers de lapin en lisant attentivement les erreurs avant le débogage.
Imprimez les variables chaque fois que possible. (C'est ce qu'on appelle le débogage printf) Vous pouvez le faire en exécutant
STDERR.puts x.inspect
ou
STDERR.puts "Variable x is #{x.inspect}"
Si vous souhaitez faciliter la saisie, vous pouvez utiliser la gemme exemplaire .
Activez les avertissements. Si vous exécutez, ruby
exécutez-le avec le -w
commutateur (par exemple ruby -w script.rb
). Si vous l'exécutez à partir d'irb et que vous utilisez une version de ruby antérieure à 1.9.2, tapez $VERBOSE = true
au début de votre session. Si vous avez mal orthographié une variable d'instance, une fois les avertissements activés, vous obtiendrez
avertissement: variable d'instance
@valeus
non initialisée
Comprendre le concept d'un hachage binaire (la citation suivante est tirée des pratiques d'un développeur agile )
Divisez l'espace du problème en deux et voyez quelle moitié contient le problème. Ensuite, divisez à nouveau cette moitié en deux et répétez.
Si vous réussissez avec un hachage binaire, vous constaterez peut-être qu'il y a une seule ligne qui ne fait pas ce que vous attendez d'elle. Par exemple
[1, 2, 3].include?([1,2])
donne une valeur de false
, même si vous pensez qu'il reviendrait true
. Dans ce cas, vous voudrez peut-être consulter la documentation. Les sites Web de documentation incluent ruby-doc.org ou APIdock . Dans ce dernier cas, vous tapez à include?
côté de la loupe près du coin supérieur droit, choisissez celui include?
qui se trouve en Array
dessous (si vous ne savez pas quelle classe [1, 2, 3]
est, tapez [1, 2, 3].class
irb), et vous pouvez inclure? (Tableau) , qui décrit ce qu'il fait.
Cependant, si la documentation ne vous aide pas, vous aurez plus de chances d'obtenir une bonne réponse si vous pouvez poser une question sur la façon dont une ligne spécifique ne fait pas ce qu'elle devrait, plutôt que sur pourquoi un script entier ne fait pas quoi cela devrait.
supprime toutes les choses
Bienvenue en 2017 ^ _ ^
D'accord, donc si vous n'êtes pas opposé à essayer un nouvel IDE, vous pouvez faire ce qui suit gratuitement .
launch.json
à utiliser "cwd"
et et "program"
à l'aide du{workspaceRoot}
macro"showDebuggerOutput"
et définissez-le surtrue
"debug.allowBreakpointsEverywhere": true
vscode
; ce n'est pas la même chose que Visual Studio . C'est gratuit, léger et généralement apprécié.View->Extensions
.vscode
et là-dedans nous ne ferons qu'un fichier appelé launch.json
où nous allons stocker quelques options de configuration.
launch.json
Contenu
{
"version": "0.2.0",
"configurations":
[
{
"name": "Debug Local File",
"type":"Ruby",
"request": "launch",
"cwd": "${workspaceRoot}",
"program": "{workspaceRoot}/../script_name.rb",
"args": [],
"showDebuggerOutput": true
}
]
}
File->Preferences->Settings
(ou Ctrl,) et faire défiler jusqu'à ce que vous atteigniez la Debug
section. Développez-le et recherchez un champ appelé "debug.allowBreakpointsEverywhere"
- sélectionnez ce champ et cliquez sur la petite icône en forme de crayon et réglez-le sur true
.Après avoir fait toutes ces choses amusantes, vous devriez être en mesure de définir des points d'arrêt et de déboguer dans un menu similaire à celui-ci pour la mi-2017 et un thème plus sombre: avec toutes les choses amusantes comme votre pile d'appels, votre visionneuse de variables, etc.
Le plus gros PITA est 1) l'installation des pré-demandes et 2) le fait de ne pas oublier de configurer le .vscode\launch.json
fichier. Seul le n ° 2 devrait ajouter des bagages aux projets futurs, et vous pouvez simplement copier une configuration suffisamment générique comme celle répertoriée ci-dessus. Il y a probablement un emplacement de configuration plus général, mais je ne sais pas d'emblée.
Je recommande vivement cette vidéo, afin de choisir le bon outil pour le moment pour déboguer notre code.
https://www.youtube.com/watch?v=GwgF8GcynV0
Personnellement, je soulignerais deux grands sujets dans cette vidéo.
C'est mes deux cents!
Toutes les autres réponses donnent déjà presque tout ... Juste un petit ajout.
Si vous voulez plus de débogueur de type IDE (non-CLI) et que vous n'avez pas peur d'utiliser Vim comme éditeur, je suggère Vim Ruby Debugger plugin pour cela.
Sa documentation est assez simple, alors suivez le lien et voyez. En bref, il vous permet de définir le point d'arrêt à la ligne actuelle dans l'éditeur, d'afficher les variables locales dans une fenêtre astucieuse en pause, de passer au-dessus / dans - presque toutes les fonctionnalités habituelles du débogueur.
Pour moi, c'était assez agréable d'utiliser ce débogueur vim pour déboguer une application Rails, bien que les riches capacités de journalisation de Rails en éliminent presque le besoin.
Je viens de découvrir ce bijou (transforme Pry en un débogueur pour MRI Ruby 2.0+)
https://github.com/deivid-rodriguez/pry-byebug
Installer avec:
gem install pry-byebug
puis utilisez exactement comme pry
, marquez la ligne à laquelle vous voulez couper:
require 'pry'; binding.pry
Contrairement à vanilla pry cependant, ce joyau a quelques commandes de navigation clés de type GDB telles que next
, step
et break
:
break SomeClass#run # Break at the start of `SomeClass#run`.
break Foo#bar if baz? # Break at `Foo#bar` only if `baz?`.
break app/models/user.rb:15 # Break at line 15 in user.rb.
break 14 # Break at line 14 in the current file.
-w
drapeau (avertissements)irb
c'est un excellent point de départ. Essayez d'utiliser irb avec de petits morceaux douteux. J'adore ruby-debug (ruby-debug19 pour Ruby 1.9+) car il permet d'arrêter facilement le programme en cours d'exécution, d'examiner les variables, de passer dans irb, puis de continuer à fonctionner.
Pour déboguer facilement le script shell Ruby, changez simplement sa première ligne de:
#!/usr/bin/env ruby
à:
#!/usr/bin/env ruby -rdebug
Ensuite, chaque fois que la console du débogueur est affichée, vous pouvez choisir:
c
pour Continuer (à l'exception suivante, au point d'arrêt ou à la ligne avec:) debugger
,n
pour la ligne suivante,w
/ where
pour afficher le cadre / la pile d'appels,l
pour afficher le code actuel,cat
pour afficher les points de capture.h
pour plus d'aide.Voir aussi: Débogage avec ruby-debug , raccourcis clavier pour la gemme ruby-debug .
Dans le cas où le script se bloque juste et que vous avez besoin d'un retour en arrière, essayez d'utiliser lldb
/ gdb
like:
echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -nf ruby)
puis vérifiez votre processus au premier plan.
Remplacez lldb
par gdb
si fonctionne mieux. Préfixe avec sudo
pour déboguer un processus n'appartenant pas.
Depuis Ruby 2.4.0, il est plus facile de démarrer une session IRB REPL au milieu de n'importe quel programme Ruby. Placez ces lignes à l'endroit du programme que vous souhaitez déboguer:
require 'irb'
binding.irb
Vous pouvez exécuter du code Ruby et imprimer des variables locales. Tapez Ctrl + D ou quit
pour terminer la REPL et laissez le programme Ruby continuer à s'exécuter.
Vous pouvez également utiliser puts
et p
pour imprimer les valeurs de votre programme pendant son exécution.
Si vous utilisez RubyMine , le débogage des scripts ruby est simple et direct.
Supposons que vous ayez un script Ruby hello_world.rb
Définissez un point d'arrêt sur la ligne 6 comme ci-dessous.
Maintenant, vous pouvez simplement démarrer le débogueur pour exécuter le script:
Ensuite, lorsque l'exécution atteint un point d'arrêt, vous pourrez inspecter les variables, etc.
débogage printf
Il y a toujours eu une controverse autour des techniques de débogage, certaines personnes aiment déboguer par des instructions d'impression, d'autres aiment creuser profondément avec un débogueur.
Je vous suggère d'essayer les deux approches.
En fait, l'un des anciens hommes d'Unix a récemment déclaré que le débogage de printf était un moyen plus rapide de le faire à certains moments.
Mais si vous êtes nouveau dans un travail et que vous avez besoin de comprendre un gros tas de code, alors il est vraiment utile de passer par là, en mettant quelques points d'arrêt ici et là, en suivant comment cela fonctionne.
Cela devrait vous permettre de comprendre comment le code est tissé.
Si vous êtes nouveau sur certains logiciels d'autres personnes, cela pourrait vous aider à passer par là.
Vous saurez rapidement s'ils l'ont arrangé de manière intelligente, ou si c'est juste un tas de merde.
Eh bien, la bibliothèque standard ruby a un débogueur de console de type gdb facile à utiliser: http://ruby-doc.org/stdlib-2.1.0/libdoc/debug/rdoc/DEBUGGER__.html Pas besoin d'installer des gemmes supplémentaires. Les scripts Rails peuvent également être débogués de cette façon.
par exemple
def say(word)
require 'debug'
puts word
end
La mère de tout débogueur est un vieil écran d'impression. La plupart du temps, vous ne voulez probablement inspecter que quelques objets simples, un moyen rapide et facile est comme ceci:
@result = fetch_result
p "--------------------------"
p @result
Cela imprimera le contenu de @result dans STDOUT avec une ligne devant pour une identification facile.
Bonus si vous utilisez un framework capable de charger / recharger automatiquement comme Rails, vous n'aurez même pas besoin de redémarrer votre application. (À moins que le code que vous déboguez ne soit pas rechargé en raison de paramètres spécifiques au framework)
Je trouve que cela fonctionne pour 90% du cas d'utilisation pour moi. Vous pouvez également utiliser ruby-debug, mais je trouve cela excessif la plupart du temps.
Il existe de nombreux débogueurs avec des fonctionnalités différentes, en fonction desquelles vous faites votre choix. Mes priorités étaient satisfaites des mouvements de levier qui étaient: