Перейти к основному содержимому

5.11. Иерархия исключений в Ruby

Разработчику Архитектору

Иерархия исключений в Ruby

Корневой класс:

  • Exception

Основные подклассы Exception:

  1. SystemExit — вызывается при завершении программы (exit, Kernel#exit).

  2. SignalException — получение сигнала ОС (например, SIGINT при нажатии Ctrl+C).

    • Interrupt — частный случай SignalException для SIGINT.
  3. ScriptError — ошибки синтаксиса и загрузки:

    • LoadError
    • NotImplementedError
    • SyntaxError
  4. StandardErrorосновной родитель для большинства исключений, возникающих в пользовательском коде.

    • ArgumentError
      • UncaughtThrowError
    • EncodingError
      • CompatibilityError
    • FiberError
    • IOError
      • EOFError
    • IndexError
      • KeyError
      • StopIteration
    • LocalJumpError
    • NameError
      • NoMethodError
    • RangeError
      • FloatDomainError
    • RegexpError
    • RuntimeError
    • SecurityError
    • SystemCallError — базовый класс для системных ошибок (аналог Errno::*).
      • Подклассы создаются динамически: Errno::ENOENT, Errno::EACCES, Errno::EEXIST и т.д.
    • ThreadError
    • TypeError
    • ZeroDivisionError
  5. fatal — внутренний псевдокласс (на самом деле не используется напрямую); некоторые фатальные ошибки VM могут быть представлены как fatal, но они не перехватываются обычным rescue.


Особенности:

  • rescue без аргументов перехватывает только StandardError и его подклассы.
    Пример:

    begin
    # ...
    rescue => e
    # то же, что rescue StandardError => e
    end
  • Чтобы перехватить все исключения (включая SystemExit, SignalException), нужно явно указать Exception:

    begin
    # ...
    rescue Exception => e
    # крайне не рекомендуется в production
    end
  • Системные ошибки (Errno::*) генерируются автоматически при ошибках системных вызовов (например, открытие несуществующего файла → Errno::ENOENT).

  • NoMethodError — одна из самых частых ошибок: вызов несуществующего метода.

  • KeyError — выбрасывается при использовании Hash#fetch с отсутствующим ключом без значения по умолчанию.

  • StopIteration — используется для завершения итераторов (внутренне в Enumerator).


Как получить список программно:

Ruby позволяет инспектировать иерархию классов:

# Все подклассы Exception
def subclasses_of(klass)
klass.subclasses + klass.subclasses.flat_map { |k| subclasses_of(k) }
end

puts subclasses_of(Exception).map(&:name).sort

Примечание: метод subclasses доступен только в режиме отладки или при подключении соответствующих утилит; в общем случае можно использовать ObjectSpace.each_object(Class).


Рекомендации:

  • Для пользовательских исключений создавайте подклассы StandardError:
    class MyCustomError < StandardError; end
  • Не перехватывайте Exception без веской причины — это может помешать корректному завершению программы (например, игнорированию Ctrl+C).