Pergunta

Eu tenho um programa Perl, que precisa de pacotes de uso (que eu também escrever). Alguns desses pacotes só são escolhidos em Runtime (baseado em alguma variável de ambiente). Eu não quero colocar no meu código uma linha de "utilização" para todos os pacotes, é claro, mas apenas uma linha "utilização", com base nesta variável, algo como:

use $ENV{a};

Infelizmente, isso não funciona, é claro. Alguma idéia de como fazer isso?

Agradecemos antecipadamente, Oren

Foi útil?

Solução

eval "require $ENV{a}";

"use" não funciona bem aqui, porque é apenas importações no contexto da eval.

Como @Manni disse, na verdade, é melhor usar exigem. Citando man perlfunc:

If EXPR is a bareword, the require assumes a ".pm" extension and 
replaces "::" with "/" in the filename for you, to make it easy to 
load standard modules.  This form of  loading of modules does not 
risk altering your namespace.

In other words, if you try this:

        require Foo::Bar;    # a splendid bareword

The require function will actually look for the "Foo/Bar.pm" file 
in the directories specified in the @INC array.

But if you try this:

        $class = 'Foo::Bar';
        require $class;      # $class is not a bareword
    #or
        require "Foo::Bar";  # not a bareword because of the ""

The require function will look for the "Foo::Bar" file in the @INC 
array and will complain about not finding "Foo::Bar" there.  In this 
case you can do:

        eval "require $class";

Outras dicas

"usa" Demonstrações são executados em tempo de compilação, não em tempo de execução. Você vai precisar para exigir seus módulos em vez disso:

my $module = "Foo::Bar";
eval "require $module";

Gostaria de usar UNIVERSAL :: exigem . Tem tanto requerem e uso métodos para usar um pacote. O uso método irá também chamar import para o pacote.

use UNIVERSAL::require;
$ENV{a}->use or die 'Could not import package:  ' . $@;

Você provavelmente vai querer usar require vez de use se você não quer que aconteça em tempo de compilação, em seguida, importe manualmente quaisquer símbolos que você pode precisar. Veja este link para o Perl Cookbook (do Google Livros) para uma boa discussão de métodos que você pode usar para conseguir o que deseja.

Eu acho que um módulo carregado no tempo de execução pode ser um Plugin. Eu tenho esse tipo de problema, tendo módulos específicos para alguns casos que são carregados em tempo de execução como plugins com Módulo :: Pluggable .

Talvez você precisa mudar a lógica de seus módulos, mas funciona e escala muito bem (meu aplicativo começou com quatro módulos e agora tem vinte e está crescendo).

Que tal usar o núcleo módulo Module :: Load

Com o seu exemplo:

use Module::Load;
load $ENV{a};

"Módulo :: Load - tempo de execução requer de ambos os módulos e arquivos"

"carga elimina a necessidade de saber se você está tentando exigem um arquivo ou um módulo."

Se ele falhar, ele vai morrer com algo parecido "Não é possível localizar xxx em @INC (@INC contém: ...".

Muitos anos depois, eval "use $mod_name"; parece funcionar muito bem (a partir de, pelo menos, 5.8.8).

A vantagem sobre eval "require $mod_name"; é que as exportações padrão do módulo carregado são automaticamente importado; Em outras palavras:

eval "use $mod_name";

é o menor equivalente a

eval "require $mod_name"; $mod_name->import();

Aqui está um comando de teste, que passa o nome do módulo via env. mod_name variável, cargas e as importações do módulo, em seguida, usa uma função importada (assume um POSIX-como shell):

 $ mod_name='Data::Dumper' perl -e 'eval "use $ENV{mod_name}"; print Dumper("hi!")'
 $VAR1 = 'hi!';

eu pode estar faltando sutilezas; se assim for, por favor me avise.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top