如何在Ruby中修复一个eval?

42

我正在尝试找出如何拯救在 Ruby 1.8.6 中使用 eval() 运行代码时遇到的语法错误。

我希望以下 Ruby 代码可以正常运行:

#!/usr/bin/ruby

good_str = "(1+1)"
bad_str = "(1+1"    # syntax error: missing closing paren

begin
    puts eval(good_str)
    puts eval(bad_str)
rescue => exc
    puts "RESCUED!"
end

运行时产生以下结果:

2
RESCUED!

相反,我得到的是:

2
eval_rescue.rb:8: (eval):1: compile error (SyntaxError)
(eval):1: syntax error, unexpected $end, expecting ')'

看起来eval方法引发的SyntaxError被某个地方捕获了,而没有让我自己处理它的机会。

有人知道如何实现我想要的行为吗(即,让我的“rescue”子句捕获来自“eval”的错误)?

2个回答

51

Brent已经找到了一个有效的答案,但我建议你尽可能少地从异常情况中恢复。这可以确保你不会意外地吞掉你不想要的东西。

因此,

begin
  puts eval(good_str)
  puts eval(bad_str)
rescue SyntaxError => se
  puts 'RESCUED!'
end

6
这是一个很好的建议。比如,捕获异常而不是语法错误(SyntaxError),可以避免在按下 ctrl-C 时中断进程。 - James Mead
我很惊讶这个最佳实践没有更广泛地被采用。 - tamouse

46

嗯,这很简单...

事实证明,在默认情况下,“rescue”语句并不捕获所有异常,而只捕获那些是StandardError子类的异常。SyntaxError是StandardError的兄弟 / 堂兄,而不是它的子类,因此rescue语句不会捕获它,除非明确告知。

如果要让rescue块捕获所有异常,则需要将代码更改为以下内容:

#!/usr/bin/ruby

good_str = "(1+1)"
bad_str = "(1+1"    # syntax error: missing closing paren

begin
    puts eval(good_str)
    puts eval(bad_str)
rescue Exception => exc
    puts "RESCUED!"
end

注意"rescue"行的更改,从"rescue => exc"变为"rescue Exception => exc"。

现在,当您运行代码时,将获得所需的结果:

2
RESCUED!

请查看此链接:https://dev59.com/R2kw5IYBdhLWcg3wNn-h - gamov

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