Является ли SystemExit особым видом исключения? - PullRequest
14 голосов
/ 25 февраля 2011

Как SystemExit ведет себя иначе, чем другие Exception с?Я думаю, что понимаю некоторые рассуждения о том, почему было бы нехорошо выдвинуть правильное Исключение.Например, вы не хотели бы, чтобы происходило что-то странное:

begin
  exit
rescue => e
  # Silently swallow up the exception and don't exit
end

Но как игнорирует rescue SystemExit?(Какие критерии он использует?)

Ответы [ 2 ]

21 голосов
/ 25 февраля 2011

Когда вы пишете rescue без одного или нескольких классов, это то же самое , что и при написании:

begin
  ...
rescue StandardError => e
  ...
end

Однако существуют исключения, которые не наследуются от StandardError. SystemExit является одним из них, и поэтому он не захвачен. Вот подмножество иерархии в Ruby 1.9.2, которую вы можете узнать сами :

BasicObject
  Exception
    NoMemoryError
    ScriptError
      LoadError
        Gem::LoadError
      NotImplementedError
      SyntaxError
    SecurityError
    SignalException
      Interrupt
    StandardError
      ArgumentError
      EncodingError
        Encoding::CompatibilityError
        Encoding::ConverterNotFoundError
        Encoding::InvalidByteSequenceError
        Encoding::UndefinedConversionError
      FiberError
      IOError
        EOFError
      IndexError
        KeyError
        StopIteration
      LocalJumpError
      NameError
        NoMethodError
      RangeError
        FloatDomainError
      RegexpError
      RuntimeError
      SystemCallError
      ThreadError
      TypeError
      ZeroDivisionError
    SystemExit
    SystemStackError
    fatal

Таким образом, вы можете захватить всего SystemExit с помощью:

begin
  ...
rescue SystemExit => e
  ...
end

... или вы можете захватить каждое исключение, включая SystemExit с:

begin
  ...
rescue Exception => e
  ...
end

Попробуйте сами:

begin
  exit 42
  puts "No no no!"
rescue Exception => e
  puts "Nice try, buddy."
end
puts "And on we run..."

#=> "Nice try, buddy."
#=> "And on we run..."

Обратите внимание, что этот пример не будет работать в (некоторых версиях?) IRB, который предоставляет собственный метод выхода, который маскирует нормальный выход Object #.

В 1.8.7:

method :exit
#=> #<Method: Object(IRB::ExtendCommandBundle)#exit>

В 1.9.3:

method :exit
#=> #<Method: main.irb_exit>
0 голосов
/ 02 марта 2017

Простой пример:

begin
  exit
  puts "never get here"
rescue SystemExit
  puts "rescued a SystemExit exception"
end

puts "after begin block"

Выход status / success? и т. Д. Также можно прочитать:

begin
  exit 1
rescue SystemExit => e
  puts "Success? #{e.success?}" # Success? false
end

begin
  exit
rescue SystemExit => e
  puts "Success? #{e.success?}" # Success? true
end

Полный список методов: [:status, :success?, :exception, :message, :backtrace, :backtrace_locations, :set_backtrace, :cause]

...