Przechwytywanie numerów linii w wyjątkach ruby

Rozważ następujący kod ruby

Test.rb:

begin

  puts
  thisFunctionDoesNotExist
  x = 1+1
rescue Exception => e
  p e
end

Do celów debugowania, chciałbym, aby blok rescue wiedział, że błąd wystąpił w linii 4 tego pliku. Jest na to jakiś czysty sposób?

Author: anshul, 2008-09-23

5 answers

p e.backtrace 

Uruchomiłem go na sesji IRB, która nie ma źródła i nadal daje istotne informacje.

=> ["(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"]

Jeśli chcesz dobrze przetworzyć backtrace, następujące wyrażenia regularne mogą być przydatne:

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 / powinien / być bezpieczny przed dziwnymi znakami w nazwach funkcji lub katalogach/nazwach plików ) ( Jeśli zastanawiasz się, gdzie pojawił się foo, zrobiłem def, aby pobrać wyjątek:

>>def foo
>>  thisFunctionDoesNotExist
>> rescue Exception => e 
>>   return e 
>>end     
>>x = foo 
>>x.backtrace
 63
Author: Kent Fredric,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 06:01:59

Możesz uzyskać dostęp do backtrace z obiektu Exception. Aby zobaczyć cały backtrace:

p e.backtrace

Będzie zawierać tablicę plików i numerów linii stosu wywołań. Dla prostego skryptu, takiego jak ten w twoim pytaniu, zawierałby tylko jedną linię.

["/Users/dan/Desktop/x.rb:4"]

Jeśli chcesz podać numer linii, możesz sprawdzić pierwszy wiersz ścieżki i wyodrębnić wartość za dwukropkiem.

p e.backtrace[0].split(":").last
 19
Author: dan-manges,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 05:50:30

Wrzucenie mojego $0.02 w ten stary wątek-- oto proste rozwiązanie, które zachowuje wszystkie oryginalne DANE:

print e.backtrace.join("\n")
 6
Author: John Bachir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-24 23:54:20

Zazwyczaj backtrace zawiera wiele linii z zewnętrznych klejnotów O wiele wygodniej jest zobaczyć tylko linie związane z samym projektem

Moją propozycją jest filtrowanie backtrace według nazwy folderu projektu

puts e.backtrace.select { |x| x.match(/HERE-IS-YOUR-PROJECT-FOLDER-NAME/) }

A następnie możesz parsować przefiltrowane linie, aby wyodrębnić numery linii zgodnie z sugestiami w innych odpowiedziach.

 5
Author: Serge Seletskyy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-06 11:26:10

Jest możliwe, że w Ruby 1.9.3 będziesz mógł uzyskać dostęp nie tylko do tych informacji w bardziej ustrukturyzowany, niezawodny i prostszy sposób bez użycia wyrażeń regularnych do cięcia łańcuchów.

Podstawową ideą jest wprowadzenie obiektu ramki wywołań, który daje dostęp do informacji o stosie wywołań.

Zobacz http://wiki.github.com/rocky/rb-threadframe / , który niestety wymaga łatania Rubiego 1.9. W RubyKaigi 2010 (koniec sierpnia 2010) planowane jest spotkanie omówienie wprowadzenia obiektu ramki do Rubiego.

Biorąc to pod uwagę, najwcześniej może się to zdarzyć w Ruby 1.9.3.

 0
Author: rocky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-21 09:08:46