Cómo rescatar una evaluación en Ruby?


Estoy tratando de averiguar cómo rescatar los errores de sintaxis que surgen cuando eval() ing código en Ruby 1.8.6.

Esperaría el siguiente código 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

Para producir el siguiente resultado cuando se ejecuta:

2
RESCUED!

En cambio, lo que obtengo es:

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

Parece que el SyntaxError planteado por el método eval está siendo rescatado en algún lugar dentro de la evaluación, sin darme la oportunidad de manejarlo yo mismo.

Cualquiera tiene idea de cómo obtener el comportamiento que quiero (es decir, para que mi cláusula 'rescate' capte el error de la 'evaluación')?

Author: George Kagan, 2009-02-12

2 answers

Brent ya tiene una respuesta que funciona, pero recomiendo rescatar del conjunto más pequeño de excepciones que puede salirse con la suya. Esto asegura que no estás engullendo accidentalmente algo que no quieres ser.

Así,

begin
  puts eval(good_str)
  puts eval(bad_str)
rescue SyntaxError => se
  puts 'RESCUED!'
end
 47
Author: James A. Rosen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:07

Bueno, eso fue fácil...

Resulta que, por defecto, la instrucción "rescue" no captura todas las excepciones, sino solo aquellas que son subclases de StandardError. SyntaxError es un hermano / primo de StandardError, no una subclase de él, por lo que la instrucción rescue no lo captura a menos que se lo indique explícitamente.

Para que el bloque de rescate capture todas las excepciones , debe cambiar el código a lo siguiente:

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

Tenga en cuenta el cambio en el " rescate" línea, de "rescue = > exc" a "rescue Exception = > exc".

Ahora, cuando ejecuta el código, obtiene los resultados deseados:

2
RESCUED!
 43
Author: Brent Chapman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-12 19:25:42