2012-07-26 7 views
5

Estoy usando reval del módulo Safe de Perl y quiero evitar que genere advertencias si la cadena que se evalúa no se puede analizar (en realidad, quiero evitar que genere advertencias) ."sin advertencias"; en un compartimento seguro

Por ejemplo, el siguiente código:

use strict; use warnings; 
use Safe;  
use feature qw/say/; 
my $cft = Safe->new; 

my $x = $cft->reval(') 1'); 
my $y = $cft->reval('2' ); 
say "x: $x"; 
say "y: $y"; 

resultados en:

Number found where operator expected at (eval 5) line 1, near ") 1" 
    (Missing operator before 1?) 
Use of uninitialized value $x in concatenation (.) or string at ./test line 12. 
x: 
y: 2 

Lo que estoy tratando de lograr es tener $ x = undef y $ y = 2, y sin advertencias Intenté poner "sin advertencias"; dentro de un ámbito nuevo, pero no tiene ningún efecto sobre las advertencias producidos desde dentro de la reval (aunque, como ha señalado @DavidO, se silencia la advertencia de valor sin inicializar '):

use strict; use warnings; 
use Safe;  
use feature qw/say/; 
my $cft = Safe->new; 
{ 
    no warnings; 
    my $x = $cft->reval(') 1'); 
    my $y = $cft->reval('2' ); 
    say "x: $x"; 
    say "y: $y"; 
} 

supongo que de alguna manera la 'no hay advertencias' debe estar dentro del compartimento seguro, así que también intenté anteponer "sin advertencias"; a las cadenas que se eval'ed:

use strict; use warnings; 
use Safe; 
use feature qw/say/; 
my $cft = Safe->new; 
{ 
    my $x = $cft->reval('no warnings;' . ') 1'); 
    my $y = $cft->reval('no warnings;' . '2' ); 
    say "x: $x"; 
    say "y: $y"; 
} 

Este reval manera no emite ninguna advertencia, pero ambas variables son no def:

Use of uninitialized value $x in concatenation (.) or string at ./test line 10. 
x: 
Use of uninitialized value $y in concatenation (.) or string at ./test line 11. 
y: 

no sé qué más para intentar, y espero que la descripción del problema era lo suficientemente clara.

+1

Su segundo intento en realidad no produce el mismo resultado que el primero. Aún produce el error de "tiempo de compilación" (en realidad, error de compilación de revalidación), pero no el aviso de tiempo de ejecución relacionado con la interpolación de un valor no inicializado en su declaración 'say'. Así que en realidad resuelve la mitad de su problema (apagó la advertencia) en su segundo fragmento de arriba. La otra mitad (silenciar el error en tiempo de compilación) es más problemática. – DavidO

+0

Sí, tienes razón sobre eso. Ni siquiera me di cuenta de eso porque mi principal preocupación aquí era realmente la revalidación: las advertencias variables no inicializadas son una consecuencia de mi intento de mantener corto el ejemplo. De todos modos, he actualizado la publicación para que quede más clara. ¡Gracias! – andrefs

Respuesta

4

Si marca [email protected], verá que $cft->reval('no warnings;' . ') 1'); ha fallado. 'require' trapped by operation mask at (eval 5) line 1.. En otras palabras, Safe está haciendo su trabajo e impide que ese código intente cargar una biblioteca.

$cft->reval('BEGIN { warnings->unimport; }) 1'); funcionaría, suponiendo que las advertencias ya están cargadas fuera del compartimento. Sin embargo, eso no silenciará los errores de tiempo de compilación. A diferencia de eval, reval parece dejarlos pasar. Usa la técnica de amon para aquietar STDERR.

+0

Un enfoque de dos niveles funciona mejor. La advertencia se genera fuera del 'reval' y se puede silenciar en ese ámbito más amplio. El error de compilación está siendo generado dentro del 'reval', y es bastante obstinado. Aquí es donde redirigir STDERR es la opción menos mala, yo. (La otra opción es permitir explícitamente 'eval' dentro del compartimento seguro, pero ¿por qué molestarse en usar Save? :)). – DavidO

+0

Aunque es divertido; la ejecución de un '' qr/[c-a]/'' dentro del compartimento de seguridad, que es una expresión regular no válida que arrojará un error mientras se está compilando, queda atrapada por revalidación. – DavidO

+0

Gracias por las respuestas. El método de @ amon parece ser la mejor alternativa para silenciar incluso los errores de análisis más severos. BEGIN {warnings-> unimport;} parece funcionar, excepto si llama explícitamente algo así como warn "foo" en la cadena que se evade: P – andrefs

4

no warnings suprime todas las advertencias que genera el use warnings pragma. Es probable que desee eliminar cualquier strict ures también. Pero los errores de análisis graves aparecerán de cualquier forma.

Si desea ejecutar ningún código, independientemente de lo patológico, sin ninguna salida a STDERR, debe modificar localmente el controlador de señal:

{ 
    # I know what I'm doing! 
    local $SIG{__WARN__} = sub {}; # locally ignore any warnings 
    eval $code; # catches all "die" 
} 

o que podría reabrir STDERR a /dev/null:

{ 
    # I know what I'm doing! 
    open my $oldSTDERR, '>&' \*STDERR or die; 
    close STDERR or die; 
    open STDERR, '>', '/dev/null' or die; 

    eval $code; 

    close STDERR or die; 
    open STDERR, '>&', $oldSTDERR or die; 
    close $oldSTDERR; 
} 
+1

Pero 'eval $ code' no está permitido dentro de un compartimiento seguro. Creo que configurar gestores '$ SIG {}' también está prohibido (y por una buena razón).Configurar un manejador '$ SIG {}' fuera del 'reval 'tampoco será efectivo. Creo que redirigir STDERR es probablemente el error más limpio con respecto al error generado al compilar el código de revalidación. La advertencia puede ser silenciada por medios normales, ya que se está produciendo fuera de la revalidación. – DavidO

+0

La primera solución propuesta por @amon está trabajando en el siguiente código: use strict; usa advertencias; use Seguro; función de uso qw/say /; my $ cft = Safe-> new; { local $ SIG {__ WARN__} = sub {}; my $ x = $ cft-> reval (') 1'); my $ y = $ cft-> reval ('2'); decir "x: $ x"; decir "y: $ y"; } Esto parece ser exactamente lo que estaba buscando, ¡gracias! – andrefs

+0

@andrefs Si esta respuesta funcionó para usted, por favor "acepte" esta respuesta para marcar su pregunta como "cerrada". – amon

Cuestiones relacionadas