Exception
处理¶ ↑
异常在 begin
/end
块中被捕获。
begin # code that might raise rescue # handle exception end
如果你在一个方法内部,除非你想限制捕获异常的范围,否则不需要使用 begin
或 end
。
def my_method # ... rescue # ... end
对于 class
,module
和 block
也是如此。
[0, 1, 2].map do |i| 10 / i rescue ZeroDivisionError nil end #=> [nil, 10, 5]
你可以通过在 rescue
行的末尾使用 => 变量名
将异常分配给一个局部变量。
begin # ... rescue => exception warn exception.message raise # re-raise the current exception end
默认情况下,StandardError
及其子类会被捕获。你可以通过在 rescue
之后列出特定的异常类(及其子类)来捕获它们。
begin # ... rescue ArgumentError, NameError # handle ArgumentError or NameError end
你可以用不同的方式捕获不同类型的异常。
begin # ... rescue ArgumentError # handle ArgumentError rescue NameError # handle NameError rescue # handle any StandardError end
异常从上到下与 rescue 部分匹配,并且只匹配一次。如果在 begin 部分引发了 ArgumentError
,它将不会在 StandardError
部分中被处理。
你可以重试捕获的异常。
begin # ... rescue # do something that may change the result of the begin block retry end
执行将从 begin 块的开头恢复,因此请注意不要创建无限循环。
在 rescue 块内是 retry
唯一有效的位置,所有其他使用都会引发 SyntaxError
。如果你想重试一个块迭代,请使用 redo
。有关详细信息,请参阅 控制表达式。
为了无论是否引发异常都始终运行一些代码,请使用 ensure
。
begin # ... rescue # ... ensure # this always runs BUT does not implicitly return the last evaluated statement. end
当没有引发异常时,你也可以运行一些代码。
begin # ... rescue # ... else # this runs only when no exception was raised AND return the last evaluated statement ensure # this always runs. # It is evaluated after the evaluation of either the `rescue` or the `else` block. # It will not return implicitly. end
注意:如果没有在 ensure
块中显式使用 return
,则 begin
/end
块将返回进入 ‘ensure’ 块之前最后求值的语句。