Considérons le code Ruby suivant
test.rb:
begin
puts
thisFunctionDoesNotExist
x = 1+1
rescue Exception => e
p e
end
Pour des raisons de débogage, j'aimerais que le bloc de secours sache que l'erreur s'est produite à la ligne 4 de ce fichier. Y a-t-il un moyen propre de le faire?
p e.backtrace
Je l'ai couru sur une session de la CISR qui n'a pas de source et il a toujours donné des informations pertinentes.
=> ["(irb):11:in `foo'",
"(irb):17:in `irb_binding'",
"/usr/lib64/Ruby/1.8/irb/workspace.rb:52:in `irb_binding'",
"/usr/lib64/Ruby/1.8/irb/workspace.rb:52"]
Si vous voulez une trace bien analysée, la regex suivante peut être utile:
p x.backtrace.map{ |x|
x.match(/^(.+?):(\d+)(|:in `(.+)')$/);
[$1,$2,$4]
}
[
["(irb)", "11", "foo"],
["(irb)", "48", "irb_binding"],
["/usr/lib64/Ruby/1.8/irb/workspace.rb", "52", "irb_binding"],
["/usr/lib64/Ruby/1.8/irb/workspace.rb", "52", nil]
]
(Regex/devrait/être en sécurité contre les caractères étranges dans les noms de fonctions ou les répertoires/noms de fichiers) (Si vous vous demandez où foo est venu, j'ai fait le choix de saisir l'exception:
>>def foo
>> thisFunctionDoesNotExist
>> rescue Exception => e
>> return e
>>end
>>x = foo
>>x.backtrace
Vous pouvez accéder à la trace à partir d'un objet Exception. Pour voir l'intégralité de la trace:
p e.backtrace
Il contiendra un tableau de fichiers et des numéros de ligne pour la pile d'appels. Pour un script simple comme celui de votre question, il ne contiendrait qu'une ligne.
["/Users/dan/Desktop/x.rb:4"]
Si vous voulez le numéro de ligne, vous pouvez examiner la première ligne de la trace, et extraire la valeur après les deux points.
p e.backtrace[0].split(":").last
En jetant 0,02 $ sur ce vieux fil, voici une solution simple qui conserve toutes les données d'origine:
print e.backtrace.join("\n")
En général, la trace contient beaucoup de lignes de gemmes externes. Il est beaucoup plus pratique de ne voir que les lignes liées au projet lui-même.
Ma suggestion est de filtrer la trace en fonction du nom du dossier du projet
puts e.backtrace.select { |x| x.match(/HERE-IS-YOUR-PROJECT-FOLDER-NAME/) }
Et ensuite, vous pouvez analyser les lignes filtrées pour extraire les numéros de ligne comme suggéré dans d'autres réponses.
Il est possible que dans Ruby 1.9.3, vous puissiez avoir accès à cette information de manière plus structurée, fiable et simple, sans utiliser d'expressions régulières pour couper des chaînes.
L'idée de base est d'introduire un objet cadre d'appel qui donne accès aux informations sur la pile d'appels.
Voir http://wiki.github.com/rocky/rb-threadframe/ , qui, hélas, nécessite l'application d'un correctif à Ruby 1.9. Dans RubyKaigi 2010 (fin août 2010), une réunion est prévue pour discuter de l'introduction d'un objet cadre dans Ruby.
Cela étant, la première chose à faire est Ruby 1.9.3.