2010-05-03 16 views
6

No estoy muy contento con la arquitectura de paso de argumentos que estoy desarrollando para los (muchos) scripts de Perl que se han desarrollado para algunos scripts que invocan varios trabajos de Hadoop MapReduce.¿Cómo puedo pasar argumentos comunes a los módulos de Perl?

Actualmente hay 8 scripts (del formulario run_something.pl) que se ejecutan desde cron. (Y más en el camino ... esperamos entre 1 y 3 más para cada función que agreguemos a hadoop.) Cada uno de estos tiene aproximadamente 6 parámetros de línea de comando idénticos, y un par de parámetros de línea de comando que son similares, todos especificados con Euclid.

Las implementaciones se encuentran en una docena de módulos .pm. Algunos de los cuales son comunes, y otras de las cuales son únicas ....

Actualmente estoy pasando los argumentos a nivel mundial para cada módulo ...

Dentro run_something.pl tengo:

set_common_args   (%ARGV); 
set_something_args  (%ARGV); 

Y dentro Something.pm tengo

sub set_something_args { (% MYARGS) = @ _; }

Entonces yo puedo hacer

if ($MYARGS{'--needs_more_beer'}) { 
    $beer++; 
} 

que estoy viendo que probablemente voy a tener archivos adicionales "comunes" que querrá pasar a args, así que voy a tener tres o cuatro llamadas set_xxx_args en la parte superior de cada run_something.pl, y simplemente no parece demasiado elegante.

Por otro lado, es mejor pasar toda la matriz de argumentos estúpidos por la cadena de llamadas, y elegir y pasar elementos individuales por la cadena de llamadas es (a) demasiado trabajo (b) propenso a errores (c) doesn ' comprar mucho

En muchas maneras lo que estoy haciendo es el diseño orientado a objetos, sin la parafernalia lenguaje orientado a objetos, y se ve feo y sin trampas dijo, pero no obstante ...

Cualquier persona tiene pensamientos o ideas?

Respuesta

4

Eche un vistazo a import en Getopt::Long. Pasa argumentos a tu módulo a través del use Module qw/.../ y los agarra a través de la subrutina import.

# Override import.                                             
sub import { 
    my $pkg = shift;   # package                                       
    my @syms =();    # symbols to import                                     
    my @config =();   # configuration                                      
    my $dest = \@syms;   # symbols first                                      
    for (@_) { 
     if ($_ eq ':config') { 
      $dest = \@config; # config next                                      
      next; 
     } 
     push(@$dest, $_);  # push                                        
    } 
    # Hide one level and call super.                                         
    local $Exporter::ExportLevel = 1; 
    push(@syms, qw(&GetOptions)) if @syms; # always export GetOptions                                
    $pkg->SUPER::import(@syms); 
    # And configure.                                             
    Configure(@config) if @config; 
} 
10

En la misma línea que la respuesta de Pedro, pero nos pasaron a utilizar y MooseMooseX::Getopt, presento la comunidad por lo que con una ... * Moose modulino: un módulo de alces que se pueden incluir y ejecutar normalmente como un módulo , o por separado como una utilidad de línea de comandos:

# this is all in one file, MyApp/Module/Foo.pm: 

package MyApp::Module::Foo; 
use Moose; 
use MooseX::Getopt; 

has [ qw(my config args here) ] => (
    is => 'ro', isa => 'Int', 
); 

sub run { ... } 

package main; 
use strict; 
use warnings; 
sub run 
{ 
    my $module = MyApp::Module::Foo->new_with_options(); 
    $module->run(); 
} 

run() unless caller(); 

El módulo se puede invocar usando:

perl MyApp/Module/Foo.pm --my 0 --config 1 --args 2 --here 3 

El uso de este patrón, puede recopilar argumentos de línea de comandos usando un módulo, que es use d por todos los demás módulos y scripts que comparten las mismas opciones, y utiliza métodos de acceso Moose estándar para recuperar esas opciones.

* Los modulinos son módulos que también se pueden ejecutar como scripts independientes: un patrón de diseño Perl del propio brian d foy de SO.

+2

O simplemente omita la regla estándar, consuma MooseX :: Runnable, y diga 'mx-run MyApp :: Module :: Foo --args --go --here'. No se requieren hacks. – jrockway

Cuestiones relacionadas