web-dev-qa-db-fra.com

Interception des numéros de ligne dans les exceptions Ruby

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?

44
anshul
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
67
Kent Fredric

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
20
dan-manges

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")
6
John Bachir

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.

5
Serge Seletskyy

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.

0
rocky