Когда вы пишете 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>