Зачисление номеров строк в исключениях рубина
Рассмотрим следующий код ruby
test.rb:
begin
puts
thisFunctionDoesNotExist
x = 1+1
rescue Exception => e
p e
end
В целях отладки я хотел бы, чтобы блок спасения знал, что ошибка произошла в строке 4 этого файла. Есть ли чистый способ сделать это?
Ответы
Ответ 1
p e.backtrace
Я запустил его на сеансе IRB, у которого нет источника, и он по-прежнему дал соответствующую информацию.
=> ["(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"]
Если вам нужна хорошо обработанная обратная трассировка, может понадобиться следующее регулярное выражение:
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/должно/быть безопасным от странных символов в именах функций или каталогах/именах файлов)
(Если вам интересно, откуда сработало foo, я решил сделать исключение:
>>def foo
>> thisFunctionDoesNotExist
>> rescue Exception => e
>> return e
>>end
>>x = foo
>>x.backtrace
Ответ 2
Вы можете получить доступ к backtrace из объекта Exception. Чтобы увидеть всю обратную трассировку:
p e.backtrace
Он будет содержать массив файлов и номеров строк для стека вызовов. Для простого script, подобного одному в вашем вопросе, он просто будет содержать одну строку.
["/Users/dan/Desktop/x.rb:4"]
Если вы хотите номер строки, вы можете проверить первую строку обратной линии и извлечь значение после двоеточия.
p e.backtrace[0].split(":").last
Ответ 3
Бросив мои $0.02 в этот старый поток - вот простое решение, которое поддерживает все исходные данные:
print e.backtrace.join("\n")
Ответ 4
Обычно backtrace содержит много строк из внешних драгоценных камней
Гораздо удобнее видеть только строки, связанные с самим проектом
Мое предложение состоит в том, чтобы отфильтровать backtrace по имени папки проекта
puts e.backtrace.select { |x| x.match(/HERE-IS-YOUR-PROJECT-FOLDER-NAME/) }
И затем вы можете проанализировать отфильтрованные строки для извлечения номеров строк, как это предлагается в других ответах.
Ответ 5
Возможно, что в Ruby 1.9.3 вы сможете получить доступ не только к этой информации более структурированным, надежным и простым способом, не используя регулярные выражения для вырезания строк.
Основная идея состоит в том, чтобы ввести объект кадра вызова, который предоставляет доступ к информации о стеке вызовов.
См. http://wiki.github.com/rocky/rb-threadframe/, который, увы, требует исправления Ruby 1.9. В RubyKaigi 2010 (конец августа 2010 года) планируется обсудить вопрос о введении объекта кадра в Ruby.
Учитывая это, самое раннее это может произойти в Ruby 1.9.3.