Como o @INC do Perl é construído?(também conhecido como Quais são todas as maneiras de afetar onde os módulos Perl são pesquisados?)
-
22-09-2019 - |
Pergunta
Quais são todas as maneiras de afetar onde os módulos Perl são pesquisados?ou, Como o @INC do Perl é construído?
Como sabemos, Perl usa @INC
array contendo nomes de diretório para determinar onde procurar por arquivos de módulo Perl.
Não parece haver uma postagem abrangente do tipo FAQ "@INC" no StackOverflow, portanto, esta pergunta pretende ser uma só.
Solução
Veremos como o conteúdo deste array é construído e pode ser manipulado para afetar onde o interpretador Perl encontrará os arquivos do módulo.
Padrão
@INC
O intérprete Perl é compilado com um específico
@INC
valor padrão.Para descobrir esse valor, executeenv -i perl -V
comando (env -i
ignora oPERL5LIB
variável ambiental - veja #2) e na saída você verá algo assim:$ env -i perl -V ... @INC: /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 .
Observação .
no final;este é o diretório atual (que não é necessariamente igual ao diretório do script).Está faltando no Perl 5.26+, e quando o Perl é executado com -T
(verificações de contaminação habilitadas).
Para alterar o caminho padrão ao configurar a compilação binária Perl, defina a opção de configuração otherlibdirs
:
Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3
Variável ambiental
PERL5LIB
(ouPERLLIB
)Perl pré-pendente
@INC
com uma lista de diretórios (separados por dois pontos) contidos emPERL5LIB
(se não estiver definido,PERLLIB
é usada) variável de ambiente do seu shell.Para ver o conteúdo de@INC
depoisPERL5LIB
ePERLLIB
variáveis de ambiente entraram em vigor, executeperl -V
.$ perl -V ... %ENV: PERL5LIB="/home/myuser/test" @INC: /home/myuser/test /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 .
-I
opção de linha de comandoPerl pré-pendente
@INC
com uma lista de diretórios (separados por dois pontos) passada como valor do-I
opção de linha de comando.Isto pode ser feito de três maneiras, como de costume com opções Perl:Passe na linha de comando:
perl -I /my/moduledir your_script.pl
Passe-o pela primeira linha (shebang) do seu script Perl:
#!/usr/local/bin/perl -w -I /my/moduledir
Passe como parte de
PERL5OPT
(ouPERLOPT
) variável de ambiente (consulte o capítulo 19.02 em Programação Perl)
Passe-o através do
lib
pragmaPerl pré-pendente
@INC
com uma lista de diretórios passados para ele viause lib
.Em um programa:
use lib ("/dir1", "/dir2");
Na linha de comando:
perl -Mlib=/dir1,/dir2
Você também pode remova os diretórios de
@INC
através dano lib
.Você pode manipular diretamente
@INC
como uma matriz Perl regular.Observação:Desde
@INC
é usado durante a fase de compilação, isso deve ser feito dentro de umBEGIN {}
bloco, que antecede ouse MyModule
declaração.Adicione diretórios ao início via
unshift @INC, $dir
.Adicione diretórios ao final via
push @INC, $dir
.Faça qualquer outra coisa que você possa fazer com um array Perl.
Observação:Os diretórios são inalterado para @INC
na ordem listada nesta resposta, por ex.padrão @INC
é o último da lista, precedido por PERL5LIB
, precedido por -I
, precedido por use lib
e direto @INC
manipulação, os dois últimos misturados em qualquer ordem em que estejam no código Perl.
Referências:
- perldoc perlmod
- biblioteca perldoc
- Perl Module Mechanics - um ótimo guia contendo COMO FAZER prático
- Como faço para 'usar' um módulo Perl em um diretório que não está
@INC
? - Programação Perl - capítulo 31 parte 13, capítulo 7.2.41
- Como um programa Perl sabe onde encontrar o arquivo que contém o módulo Perl que ele usa?
Não parece haver uma abordagem abrangente @INC
Postagem do tipo FAQ no Stack Overflow, portanto, esta pergunta pretende ser uma só.
Quando usar cada abordagem?
Se os módulos em um diretório precisarem ser usados por muitos/todos os scripts em seu site, especialmente executados por vários usuários, esse diretório deverá ser incluído no padrão
@INC
compilado no binário Perl.Se os módulos no diretório forem usados exclusivamente por um usuário específico para todos os scripts que o usuário executa (ou se recompilar o Perl não for uma opção para alterar o padrão
@INC
no caso de uso anterior), defina os usuáriosPERL5LIB
, geralmente durante o login do usuário.Observação:Por favor, esteja ciente das armadilhas usuais das variáveis de ambiente Unix - por exemplo.em certos casos, a execução dos scripts como um usuário específico não garante sua execução com o ambiente desse usuário configurado, por exemplo.através da
su
.Se os módulos no diretório precisarem ser usados apenas em circunstâncias específicas (por exemplo,quando o(s) script(s) são executados no modo de desenvolvimento/depuração, você pode definir
PERL5LIB
manualmente ou passe o-I
opção para perl.Se os módulos precisarem ser usados apenas para scripts específicos, por todos usuários que os utilizam, use
use lib
/no lib
pragmas no próprio programa.Também deve ser usado quando o diretório a ser pesquisado precisa ser determinado dinamicamente durante o tempo de execução - por exemplo.dos parâmetros de linha de comando do script ou do caminho do script (consulte o EncontrarBin módulo para um caso de uso muito bom).Se os diretórios em
@INC
precisam ser manipulados de acordo com alguma lógica complicada, impossível ou muito difícil de implementar pela combinação deuse lib
/no lib
pragmas, então use direto@INC
manipulação dentroBEGIN {}
bloco ou dentro de uma biblioteca para fins especiais designada para@INC
manipulação, que deve ser usada pelo(s) seu(s) script(s) antes de qualquer outro módulo ser usado.Um exemplo disso é alternar automaticamente entre bibliotecas nos diretórios prod/uat/dev, com coleta de biblioteca em cascata no prod se estiver faltando em dev e/ou UAT (a última condição torna a solução padrão "use lib + FindBin" bastante complicada.Uma ilustração detalhada deste cenário está em Como faço para usar módulos beta Perl de scripts beta Perl?.
Um caso de uso adicional para manipulação direta
@INC
é poder adicionar referências de sub-rotinas ou referências de objetos (sim, Virginia,@INC
pode conter código Perl personalizado e não apenas nomes de diretório, conforme explicado em Quando é chamada uma referência de sub-rotina em @INC?).
Outras dicas
Além dos locais listados acima, a versão OS X do Perl também tem mais duas maneiras:
O arquivo /library/perl/x.xx/appendtopath. Os caminhos listados neste arquivo são anexados ao @inc em tempo de execução.
O arquivo /library/perl/x.xx/prependtopath. Os caminhos listados neste arquivo são antecipados para @inc em tempo de execução.
Como já foi dito, o @inc é uma matriz e você está livre para adicionar o que quiser.
Meu script de repouso CGI se parece:
#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
push @INC, 'fully_qualified_path_to_module_wiht_our_REST.pm';
}
use Modules::Rest;
gone(@_);
A sub -rotina foi exportada por Rest.Pm.