2010-02-04 29 views
7

Tengo un programa Perl que genera reglas de análisis como subs de un archivo de entrada. Los subs se definen anónimamente y se ponen en un hash. Ahora, quiero exportar ese hash, con todos los subs y luego volver a cargarlos para usarlos con un programa diferente.Escribir un sub anónimo en Perl en un archivo para su uso posterior

¿Cómo puedo hacer esto? ¿Hay alguna forma de extraer el código de cada sub o puedo copiar el bloque de memoria en el que existe el hash y luego convertirlo en hash cuando lo vuelva a cargar más tarde?

Gracias de antemano.

+0

En lugar de guardar los submarinos compilados reales, que podrían salvar el texto * * de los submarinos y, a continuación, re-eval en coderefs en el nuevo proceso. – Ether

+0

Sí, pensé en eso. Pero me gustaría poder guardar los subs compilados por razones estéticas. :-p –

+0

Todas las técnicas que conozco usan B :: Deparse para traducir la referencia del código nuevamente al código fuente de Perl. Este proceso puede no devolverle el mismo código fuente con el que comenzó. No creo que esto te compre mucho más que simplemente guardar el texto original. –

Respuesta

2

Desde la sección "Code References" de la documentación para almacenar (con énfasis añadido):

Desde almacenable versión 2.05, las referencias de código pueden ser serializados con la ayuda de B::Deparse. Para habilitar esta función, configure $Storable::Deparse en un valor verdadero. Para habilitar la deserialización, $Storable::Eval debe establecerse en un valor verdadero. Tenga en cuenta que la deserialización se realiza a través de eval, lo cual es peligroso si el archivo Almacenable contiene datos maliciosos.

En la demostración a continuación, un proceso secundario crea el hash de subs anónimos. A continuación, el elemento primario, en un espacio de proceso y dirección por separado, por lo que no puede ver %dispatch, lee la salida de freeze de la misma forma que podría hacerlo desde un archivo en el disco.

#! /usr/bin/perl 

use warnings; 
use strict; 

use Storable qw/ freeze thaw /; 

my $pid = open my $fh, "-|"; 
die "$0: fork: $!" unless defined $pid; 

if ($pid == 0) { 
    # child process 
    my %dispatch = (
    foo => sub { print "Yo!\n" }, 
    bar => sub { print "Hi!\n" }, 
    baz => sub { print "Holla!\n" }, 
); 

    local $Storable::Deparse = 1 || $Storable::Deparse; 
    binmode STDOUT, ":bytes"; 
    print freeze \%dispatch; 
    exit 0; 
} 
else { 
    # parent process 
    local $/; 
    binmode $fh, ":bytes"; 
    my $frozen = <$fh>; 

    local $Storable::Eval = 1 || $Storable::Eval; 
    my $d = thaw $frozen; 
    $d->{$_}() for keys %$d; 
} 

Salida:

Hi! 
Holla! 
Yo!
+0

y simplemente puedo escribir '$ frozen' en un archivo de texto? y no te preocupes, voy a desinfectar mis entradas. Esto lo aprendí de XKCD: D –

+0

@Mechko Sí, en tu código, escribirías el resultado en un archivo en el disco y luego lo leerías más tarde. Cambié la demostración para que se pareciera a los dos lados de tu canalización. –

4

KiokuDB puede manejar el almacenamiento de referencias de código además de otros tipos de Perl. También lo pueden hacer los diversos módulos YAML, Data::Dump::Streamer, e incluso Data :: Dumper.

Cuestiones relacionadas