Evgenii Legotckoi
Aug. 26, 2016, 1:09 p.m.

User Guide #24 - Ruby - Exception processing: rescue

An executing program can run into unexpected problems. A file that it wants to read might not exist; the disk might be full when it wants to save some data; the user may provide it with some unsuitable kind of input.

  1. ruby> **file = open("some_file")**
  2. **ERR: (eval):1:in `open': No such file or directory - some_file**

A robust program will handle these situations sensibly and gracefully. Meeting that expectation can be an exasperating task. C programmers are expected to check the result of every system call that could possibly fail, and immediately decide what is to be done:

  1. FILE *file = fopen("some_file", "r");
  2. if (file == NULL) {
  3.   fprintf( stderr, "File doesn't exist.\n" );
  4.   exit(1);
  5. }
  6. bytes_read = fread( buf, 1, bytes_desired, file );
  7. if (bytes_read != bytes_desired ) {
  8.   /* do more error handling here ... */
  9. }
  10. ...

This is such a tiresome practice that programmers can tend to grow careless and neglect it, and the result is a program that doesn't handle exceptions well. On the other hand, doing the job right can make programs hard to read, because there is so much error handling cluttering up the meaningful code.

In ruby, as in many modern languages, we can handle exceptions for blocks of code in a compartmentalized way, thus dealing with surprises effectively but not unduly burdening either the programmer or anyone else trying to read the code later. The block of code marked with

  1. begin
executes until there is an exception, which causes control to be transferred to a block of error handling code, which is marked with
  1. rescue
. If no exception occurs, the
  1. rescue
code is not used. The following method returns the first line of a text file, or
  1. nil
if there is an exception:

  1. def first_line( filename )
  2.   begin
  3.     file = open("some_file")
  4.     info = file.gets
  5.     file.close
  6.     info  # Last thing evaluated is the return value
  7.   rescue
  8.     nil   # Can't read the file? then don't return a string
  9.   end
  10. end

There will be times when we would like to be able to creatively work around a problem. Here, if the file we want is unavailable, we try to use standard input instead:

  1. begin
  2.   file = open("some_file")
  3. rescue
  4.   file = STDIN
  5. end
  6.  
  7. begin
  8.   # ... process the input ...
  9. rescue
  10.   # ... and deal with any other exceptions here.
  11. end

  1. retry
can be used in the
  1. rescue
code to start the
  1. begin
code over again. It lets us rewrite the previous example a little more compactly:

  1. fname = "some_file"
  2. begin
  3.   file = open(fname)
  4.   # ... process the input ...
  5. rescue
  6.   fname = "STDIN"
  7.   retry
  8. end

However, there is a flaw here. A nonexistent file will make this code retry in an infinite loop. You need to watch out for such pitfalls when using

  1. retry
for exception processing.

Every ruby library raises an exception if any error occurs, and you can raise exceptions explicitly in your code too. To raise an exception, use

  1. raise
. It takes one argument, which should be a string that describes the exception. The argument is optional but should not be omitted. It can be accessed later via the special global variable
  1. $!
.

  1. ruby> **raise "test error"**
  2. **test error**
  3. ruby> **begin**
  4.     |**raise "test2"**
  5.     | **rescue**
  6.     |**print "An error occurred: ",$!, "\n"**
  7.     | **end**
  8. An error occurred: test2
  9. **nil**

Do you like it? Share on social networks!

Comments

Only authorized users can post comments.
Please, Log in or Sign up
  • Last comments
  • Evgenii Legotckoi
    April 16, 2025, 5:08 p.m.
    Благодарю за отзыв. И вам желаю всяческих успехов!
  • IscanderChe
    April 12, 2025, 5:12 p.m.
    Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
  • AK
    April 1, 2025, 11:41 a.m.
    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
  • Evgenii Legotckoi
    March 9, 2025, 9:02 p.m.
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    March 9, 2025, 4:14 p.m.
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…