coderrr

November 7, 2008

The simple way to print exceptions in Ruby

Filed under: ruby — Tags: — coderrr @ 9:02 am

Shameless Plug: Don’t make any exceptions. Protect your privacy online with a VPN Service when browsing the web.

update:
p $!, *$@ is a little more optimal in that you will see the class of the exception also.

I’ll put the meat of this post first so you don’t have to waste your time if you already know this. The simplest way to catch and print out an exception along with it’s backtrace:

# catch most exceptions (anything that derives from StandardError)
begin
  ...
rescue
  puts $!, $@
end

# catch all exceptions (anything that derives from Exception)
begin
  ...
rescue Exception
  puts $!, $@
end

At some point we all want to catch an exception, print it out, and then move on to something else. I just wanted to point out a very simple way to do this. I want to point this out because I have seen many people spend far too much typing on this (myself included). Here’s a combined example of the overtyping I’ve seen used.

begin
  ...
rescue Exception => ex
  puts ex.message
  puts ex.backtrace.join("\n")
end

First off, Ruby stores the last exception caught in the special (thread local) variable $! and the backtrace of the last exception in $@. So there is no need to explicitly specify a variable to store it in. Secondly, Exception#message in most cases is redundant because it’s just aliased to Exception#to_s which puts will call for you. Thirdly calling join("\n") is redundant when passing an array to puts. By default puts will output an array with a newline between each item. Also you might not have known that you can pass multiple arguments to puts and it will be just as if you had called puts for each one.

Usually the message of the exception is clear enough so you don’t need to see its class. But in the cases where you want to, we can easily show this too without much more work:

rescue
  p $!
  puts $@
end

# or

rescue
  puts $!.inspect, $@
end

p will call inspect on the exception which will show it’s class and message.

I know this is simple and trivial stuff but I still see a lot of people doing it a more verbose way than necessary. Some people will probably argue that it’s less understandable my way or we should be more explicit or something and that’s a matter of opinion but I personally disagree with it. Anyway this post is mainly for the people who would like doing it the shorter way but just didn’t know about it yet.

9 Comments »

  1. That’s helpful, thanks! :)

    Comment by Noam B — November 7, 2008 @ 10:50 am

  2. Don’t get me wrong but I think it’s bullshit. Give me a person which will remember all this $#@!%#@! crypto named variables. Yep, Matz when created Ruby liked also Perl. He thought that all these magic variables are great. But 15 years later most people will agree: they don’t and they don’t match with Ruby. Fortunately most people don’t use them.

    Try it with your colleges, show your code and ask them what $! and $@ means. Show them also e.message and e.backtrace and I’m sure that (even when don’t know Ruby at all) they will know.

    Programming isn’t about writing the shortest code as you can. Programming is about balancing between readability, verbosity and quantity of source code. Without good proportions your end up with java or perl.

    Comment by Radarek — November 7, 2008 @ 2:07 pm

  3. I agree with Radarek. I’ll take readable ‘verbose’ code over a splattering of $@$! any day. I actually like the idea of dropping the join and combining the puts, resulting in:

    rescue Exception => e
    puts e.message, e.backtrace
    end

    That’s very succinct, yet completely understandable.

    Comment by Dean Strelau — November 7, 2008 @ 2:15 pm

  4. This really comes to down to who you’re programming for and personal style. If either one dictates you should use a more verbose syntax then by all means please do.

    In regards to the “=> e” I just think it’s the most redundant thing ever. What ELSE are you going to do in a rescue block other than access the exception object. I think if you saw a $! inside of a rescue block for the first time it’d be pretty easy to deduce what it is.

    Now one thing I don’t and haven’t recommended is using $! in some method which you call from the rescue block. In that case I would definitely recommend passing it to the method.

    Comment by coderrr — November 7, 2008 @ 2:34 pm

  5. perl has english version of these variables ($! is also $ERRNO and $OS_ERROR, $@ is also $EVAL_ERROR, etc… see man perlvar for all the others).

    Know if ruby also has readable name for these variables ?

    Comment by Thierry — November 7, 2008 @ 7:47 pm

  6. $! == $ERROR_INFO
    $@ == $ERROR_POSITION

    There – no need to use meaningless punctuation.

    But note the $. Global variables are bad. I’m not going to argue about it, since other people have done a far better job than I can over the last 30 or 40 years. If someone disagrees that globals should only be used when absolutely necessary, fine.

    However, I do sympathize with the discomfort of declaring a variable to hold the exception, when it’s not really serving any purpose to do so. Perhaps the best solution would be an automatically defined variable (like $ERROR_INFO) that would be local to the current exception handler.

    Either way, I think ‘=> e’ is far to be preferred over cryptic, Perly, global variables. Even if someone could intuit what $! means, what about $@? C’mon.

    Comment by Mark Wilden — November 11, 2008 @ 12:02 am

  7. Do you really mean that Exception#message is _always_ redundant because it’s _always_ aliased to puts? If not, what are the situations where it’s NOT simply aliased to #to_s?

    Is any such discrepancy between ruby versions? Subclasses of Exception? I ask because I initialized a Hash by passing in an array (see Hash[]) and it differed between ruby 1.8.4 and 1.8.7. I’ve come to be aware of such caveats.

    Comment by Joshua Go — November 20, 2008 @ 1:09 am

  8. 1.8:

    rb_define_method(rb_eException, “message”, exc_to_str, 0);

    exc_to_str of course calls to_s…

    Any subclass could override #message to do something different. I haven’t done an investigation of this but I have a feeling you won’t find many cases where they do that.

    In 1.9 it’s the same.

    Comment by coderrr — November 20, 2008 @ 9:40 am

  9. Don’t forget that you can just raise the error again, and it will be printed if it is not caught. This is good if your goal is just to print the error, and you don’t care about recovering from the error; the only reason you caught the error was to log it in a special way. So your code might be like this:

    begin
    results = calculate_values(data)
    upload_results_with_api(connector, results)
    alert_script_success(true)
    rescue Exception
    alert_script_success(false)
    raise
    end

    Comment by Rory O’Kane — June 19, 2012 @ 5:44 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Customized Silver is the New Black Theme Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 28 other followers

%d bloggers like this: