Is SystemExit a special kind of Exception?
How does SystemExit
behave differently from other Exception
s? I think I understand some of the reasoning about why it wouldn't be go开发者_运维知识库od to raise a proper Exception. For example, you wouldn't want something strange like this to happen:
begin
exit
rescue => e
# Silently swallow up the exception and don't exit
end
But how does the rescue
ignore SystemExit
? (What criteria does it use?)
When you write rescue
without one or more classes, it is the same as writing:
begin
...
rescue StandardError => e
...
end
There are Exceptions that do not inherit from StandardError
, however. SystemExit
is one of these, and so it is not captured. Here is a subset of the hierarchy in Ruby 1.9.2, which you can find out yourself:
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
You can thus capture just SystemExit
with:
begin
...
rescue SystemExit => e
...
end
...or you can choose to capture every exception, including SystemExit
with:
begin
...
rescue Exception => e
...
end
Try it yourself:
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..."
Note that this example will not work in (some versions of?) IRB, which supplies its own exit method that masks the normal Object#exit.
In 1.8.7:
method :exit
#=> #<Method: Object(IRB::ExtendCommandBundle)#exit>
In 1.9.3:
method :exit
#=> #<Method: main.irb_exit>
Simple example:
begin
exit
puts "never get here"
rescue SystemExit
puts "rescued a SystemExit exception"
end
puts "after begin block"
The exit status
/ success?
, etc. can be read too:
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
Full list of methods: [:status, :success?, :exception, :message, :backtrace, :backtrace_locations, :set_backtrace, :cause]
精彩评论