关于异常:如何在Ruby中拯救eval?

How to rescue an eval in Ruby?

我正在尝试解决Ruby1.8.6中的eval()ing代码时出现的语法错误。

我希望得到以下Ruby代码:

1
2
3
4
5
6
7
8
9
10
11
#!/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

运行时生成以下结果:

1
2
2
RESCUED!

相反,我得到的是:

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

似乎eval方法引发的syntaxerror正在eval中的某个地方被挽救,而没有给我自己处理它的机会。

有人知道如何得到我想要的行为(也就是说,为了我的"拯救"条款从"eval"中捕获错误)吗?


布伦特已经得到了一个可行的答案,但我建议你从你能摆脱的最小的例外中拯救出来。这可以确保你不会意外地吞下你不想成为的东西。

因此,

1
2
3
4
5
6
begin
  puts eval(good_str)
  puts eval(bad_str)
rescue SyntaxError => se
  puts 'RESCUED!'
end


很简单…

结果表明,默认情况下,"rescue"语句不会捕获所有异常,而只捕获属于StandardError子类的异常。syntaxerror是standarderror的兄弟/表亲,而不是它的子类,因此除非明确告知,否则rescue语句不会捕获它。

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

1
2
3
4
5
6
7
8
9
10
11
#!/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"。

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

1
2
2
RESCUED!