Как спасти eval в Ruby? - PullRequest
       16

Как спасти eval в Ruby?

38 голосов
/ 12 февраля 2009

Я пытаюсь выяснить, как спасти синтаксические ошибки, возникающие при eval() кодировании в Ruby 1.8.6.

Я бы ожидал следующий код 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 ')'

Похоже, что ошибка SyntaxError, вызванная методом eval, спасается где-то внутри eval, не давая мне возможности обработать ее самостоятельно.

У кого-нибудь есть идеи, как получить желаемое поведение (т. Е. Чтобы мой пункт 'rescue' поймал ошибку из 'eval')?

Ответы [ 2 ]

48 голосов
/ 12 февраля 2009

Брент уже получил ответ , который работает , но я рекомендую избавиться от наименьшего набора исключений, с которым вы можете сойти. Это гарантирует, что вы случайно не сожраете то, чем не хотите быть.

Таким образом,

begin
  puts eval(good_str)
  puts eval(bad_str)
rescue SyntaxError => se
  puts 'RESCUED!'
end
43 голосов
/ 12 февраля 2009

Ну, это было легко ...

Оказывается, что по умолчанию оператор "rescue" не перехватывает все исключения, а только те, которые являются подклассами StandardError. SyntaxError - это родственник / двоюродный брат StandardError, а не его подкласс, поэтому оператор спасения не захватывает его, если ему явно не сказано.

Чтобы блок спасения захватывал все исключений, вам необходимо изменить код на следующий:

#!/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!
...