Is SystemExit a special kind of Exception?

前端 未结 2 1053
北海茫月
北海茫月 2020-12-17 15:30

How does SystemExit behave differently from other Exceptions? I think I understand some of the reasoning about why it wouldn\'t be good t

相关标签:
2条回答
  • 2020-12-17 16:21

    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>
    
    0 讨论(0)
  • 2020-12-17 16:30

    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]

    0 讨论(0)
提交回复
热议问题