tags:

views:

1549

answers:

4

Consider the following ruby code

test.rb:

begin

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

For debugging purposes, I would like the rescue block to know that the error occurred in line 4 of this file. Is there a clean way of doing that?

+8  A: 
p e.backtrace

I ran it on an IRB session which has no source and it still gave relevant info.

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

If you want a nicely parsed backtrace, the following regex might be handy:

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 /should/ be safe against weird characters in function names or directories/filenames ) ( If you're wondering where foo camefrom, i made a def to grab the exception out :

>>def foo
>>  thisFunctionDoesNotExist
>> rescue Exception => e 
>>   return e 
>>end     
>>x = foo 
>>x.backtrace
Kent Fredric
+6  A: 

You can access the backtrace from an Exception object. To see the entire backtrace:

p e.backtrace

It will contain an array of files and line numbers for the call stack. For a simple script like the one in your question, it would just contain one line.

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

If you want the line number, you can examine the first line of the backtrace, and extract the value after the colon.

p e.backtrace[0].split(":").last
dan-manges
A: 

It is possible that in Ruby 1.9.3 you will be able to get access to not only this information in a more structured, reliable, and simpler way without using regular expressions to cut strings.

The basic idea is to introduce a call frame object which gives access to information about the call stack.

See http://wiki.github.com/rocky/rb-threadframe/, which alas, requires patching Ruby 1.9. In RubyKaigi 2010 (late August 2010) a meeting is scheduled to discuss introducing a frame object into Ruby.

Given this, the earliest this could happen is in Ruby 1.9.3.

rocky
A: 

Throwing my $0.02 in on this old thread-- here's a simple solution that maintains all the original data:

print e.backtrace.join("\n")
John