Rails 关于 Don't rescue Exception 的疑问

night_7th · 2016年01月19日 · 最后由 adamshen 回复于 2016年01月20日 · 2921 次阅读

今天看到了Rails Best Practice中的这么一条建议,Don't rescue Exception:

Don't rescue Exception, rescue StandardError Explicitly rescuing Exception will rescue even not normally recoverable errors such as SyntaxError, LoadError, and Interrupt.

然而我自己在 demo 项目中测试了一下:

def index
  a )= 2 # Syntax error here
  @books = Book.all
rescue Exception => e
  logger.info "#{e}"
end

运行项目时却正常报错了,并没有被 rescue:

SyntaxError (/app/controllers/books_controller.rb:7: syntax error, unexpected ')', expecting keyword_end
    a )= 2
       ^):

我的 rails 版本是 4.2.5,很好奇是否这条规则已经失效了。

建议先看看 SyntaxError、StandardError 和 Exception 的关系。

def index
  eval("a )= 2") # Syntax error here
  @books = Book.all
rescue Exception => e
  logger.info "#{e}"
end

可能这条规则针对的是这种用 eval 出 SyntaxError 的情形吧

@night_7th 感觉这里不必拘泥于是否捕获了SyntaxError,而要看到本质:Exception囊括了很多本不该我们捕获的异常,比如Interrupt,NoMemoryError。

Exception
  NoMemoryError
  ScriptError
    LoadError
    NotImplementedError
    SyntaxError
  SignalException
    Interrupt
      Timeout::Error    # < ruby 1.9.2
  StandardError         # caught by rescue (default if no type was specified)
    ArgumentError
    IOError
      EOFError
    IndexError
    LocalJumpError
    NameError
      NoMethodError
    RangeError
      FloatDomainError
    RegexpError
    RuntimeError
      Timeout::Error    # >= ruby 1.9.2
    SecurityError
    SocketError
    SystemCallError
    SystemStackError
    ThreadError
    TypeError
    ZeroDivisionError
  SystemExit
  fatal

这个我记得 stackoverflow 上也有同样的问题。

@dorentus eval确实被 rescue 捕获住了,神奇

@qinfanpeng :plus1: 我就是好奇,因为syntax error最容易复现,就尝试了下

@adamshen 是这个么?

#6 楼 @night_7th 对的,这个 vote 数量很高的,当初出于好奇把 vote 前几页的问题都看了一遍,最高的居然是怎么写一个 case 语句,原来老外也是不看语法书的哈哈。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号