Begin Rescue无法捕获错误

25

我正在使用一些包含在 begin - rescue 块中的 Ruby 代码,但是它仍然会崩溃。

这个代码块看起来像这样:

# Retrieve messages from server
def get_messages
  @connection.select('INBOX')
  @connection.uid_search(['ALL']).each do |uid|
    msg = @connection.uid_fetch(uid,'RFC822').first.attr['RFC822']
    begin
      process_message(msg)
      add_to_processed_folder(uid) if @processed_folder
    rescue
       handle_bogus_message(msg)
    end
    # Mark message as deleted 
    @connection.uid_store(uid, "+FLAGS", [:Seen, :Deleted])
  end
end

考虑到这段代码,我会认为当process_messageadd_to_processed_folder无法执行时,程序会执行handle_bogus_message。话虽如此,我在生产环境下运行这段代码时(从一个Rake任务中运行),有时会因为SyntaxError而终止。

要查看错误信息,请访问http://pastie.org/1028479,请注意它所提到的process_message与上面的相同。是否有任何理由使得begin-rescue无法捕获此异常?

2个回答

51

rescue在没有参数的情况下只会捕获继承自StandardError的异常。要捕获SyntaxError,请使用rescue SyntaxError

要捕获所有异常,请使用rescue Exception,但请注意,这是一个不好的做法(这也是为什么rescue的默认行为不是这样)如此处此处所解释的那样。特别是以下部分:

捕获Interrupt会阻止用户使用CTRL+C退出程序。

捕获SignalException会阻止程序对信号作出正确响应。它只能通过kill -9命令强制终止。


5
默认情况下 rescue 不会捕获 Exception 的原因是,它们通常被认为过于严重而不适合被捕获。 - Andrew Grimm
出于某种原因,这仍然没有捕获SyntaxError。在重新引发异常之前,我正在添加额外的日志记录。客户端实际问题是他们得到了未转义的RegExp,而我在尝试复制问题时遇到了SyntaxError。 - The Human Cat

3

rescue 不带参数时只接受由 StandardError 类引发的异常。您的错误类型是 SyntaxError,它继承自一个名为 ScriptError 的不同类。所有这些错误类都是 Exception 类的子类。因此,如 sepp2k 建议的那样使用 rescue Exception 来捕获所有类型的异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接