¿Cómo se construye el @INC de Perl? (también conocido como ¿Cuáles son todas las formas de afectar dónde se buscan los módulos de Perl?)

199

¿Cuáles son todas las formas de afectar dónde se buscan los módulos Perl? o ¿Cómo se construye el @INC de Perl ?

Como sabemos, Perl usa una @INCmatriz que contiene nombres de directorio para determinar dónde buscar los archivos del módulo Perl .

No parece haber una publicación de tipo de preguntas frecuentes "@INC" exhaustiva en StackOverflow, por lo que esta pregunta está pensada como una.

DVK
fuente
77
Sí, pero hay uno perfectamente bueno en search.cpan.org/perldoc/… ?
mafia
3
@mobrule: No creo que sea tan completo, solo dice cómo agregar @INCen tiempo de ejecución, no la construcción completa.
Cascabel
2
@mobrule - @Jefromi acertó - el principal problema con CUALQUIERA y todas las referencias que encontré hasta ahora fue la falta de información completa sobre el valor predeterminado compilado de perl binary @INC
DVK
3
Algunos pueden hacer que la respuesta sea tan completa enviándome un parche. Es fácil porque perlfaq está en Github. :)
brian d foy
1
Bueno, la "información completa sobre el valor predeterminado compilado de perl binary @INC" es que es la persona que lo compiló. Si pregunta por los diversos caminos que se encuentran allí, creo que tiene una pregunta diferente a la que respondió.
brian d foy

Respuestas:

254

Veremos cómo se construyen los contenidos de esta matriz y cómo se pueden manipular para afectar el lugar donde el intérprete de Perl encontrará los archivos del módulo.

  1. Defecto @INC

    El intérprete de Perl se compila con un @INCvalor predeterminado específico . Para encontrar este valor, ejecute el env -i perl -Vcomando ( env -iignora la PERL5LIBvariable de entorno - vea # 2) y en la salida verá algo como esto:

    $ 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
     .

Nota .al final; Este es el directorio actual (que no es necesariamente el mismo que el directorio del script). Falta en Perl 5.26+, y cuando Perl se ejecuta con -T(comprobaciones de manchas habilitadas) .

Para cambiar la ruta predeterminada al configurar la compilación binaria Perl, configure la opción de configuración otherlibdirs:

Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3

  1. Variable ambiental PERL5LIB(o PERLLIB)

    Perl se antepone @INCcon una lista de directorios (separados por dos puntos) contenidos en PERL5LIB(si no se define, PERLLIBse usa) la variable de entorno de su shell. Para ver el contenido de @INCafter PERL5LIBy PERLLIBlas variables de entorno han tenido efecto, ejecute perl -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
     .
  2. -I opción de línea de comandos

    Perl se antepone @INCcon una lista de directorios (separados por dos puntos) pasados ​​como valor de la -Iopción de línea de comandos. Esto se puede hacer de tres maneras, como es habitual con las opciones de Perl:

    • Pásalo en la línea de comando:

      perl -I /my/moduledir your_script.pl
    • Pásalo a través de la primera línea (shebang) de tu script Perl:

      #!/usr/local/bin/perl -w -I /my/moduledir
    • Pásalo como parte de PERL5OPT(o PERLOPT) variable de entorno (ver capítulo 19.02 en Programación Perl )

  3. Pásalo por el libpragma

    Perl se antepone @INCcon una lista de directorios pasados ​​a través de use lib.

    En un programa:

    use lib ("/dir1", "/dir2");

    En la línea de comando:

    perl -Mlib=/dir1,/dir2

    También puede eliminar los directorios de @INCviano lib .

  4. Puede manipular directamente @INCcomo una matriz Perl normal.

    Nota: Dado que @INCse usa durante la fase de compilación, esto debe hacerse dentro de un BEGIN {}bloque, que precede a la use MyModuledeclaración.

    • Agregar directorios al principio a través de unshift @INC, $dir.

    • Agregue directorios al final a través de push @INC, $dir.

    • Haga cualquier otra cosa que pueda hacer con una matriz Perl.

Nota: Los directorios son no desplazada en @INCel orden indicado en esta respuesta, por ejemplo, por defecto @INCes el último en la lista, precedido por PERL5LIB, precedida por -I, precedidos por use libdirecto y @INCla manipulación, los dos últimos mezclarse en cualquier orden en que están en código Perl.

Referencias

No parece haber una @INCpublicación completa de tipo FAQ en Stack Overflow, por lo que esta pregunta está pensada como una.

¿Cuándo usar cada enfoque?

  • Si los módulos en un directorio necesitan ser utilizados por muchos / todos los scripts en su sitio, especialmente ejecutados por múltiples usuarios, ese directorio debe incluirse en el @INCcompilado predeterminado en el binario de Perl.

  • Si los módulos en el directorio serán utilizados exclusivamente por un usuario específico para todos los scripts que ejecuta el usuario (o si recompilar Perl no es una opción para cambiar el valor predeterminado @INCen el caso de uso anterior), configure los usuarios PERL5LIB, generalmente durante el inicio de sesión del usuario.

    Nota: Tenga en cuenta las dificultades habituales de las variables de entorno Unix, por ejemplo, en ciertos casos, ejecutar los scripts ya que un usuario en particular no garantiza ejecutarlos con la configuración del entorno de ese usuario, por ejemplo, a través de su.

  • Si los módulos en el directorio necesitan usarse solo en circunstancias específicas (por ejemplo, cuando el script (s) se ejecuta en modo de desarrollo / depuración, puede configurarlo PERL5LIBmanualmente o pasar la -Iopción a perl.

  • Si los módulos necesitan ser utilizados solo para scripts específicos, por todos los usuarios que los usen, use use lib/ no libpragmas en el programa mismo. También debe usarse cuando el directorio a buscar debe determinarse dinámicamente durante el tiempo de ejecución, por ejemplo, a partir de los parámetros de la línea de comandos o la ruta del script (consulte el módulo FindBin para obtener un caso de uso muy agradable).

  • Si los directorios @INCnecesitan ser manipulados de acuerdo con una lógica complicada, ya sea imposible o demasiado difícil de implementar mediante la combinación de use lib/ no libpragmas, entonces use la @INCmanipulación directa dentro del BEGIN {}bloque o dentro de una biblioteca de propósito especial designada para la @INCmanipulación, que debe ser utilizada por su script (s) antes de utilizar cualquier otro módulo.

    Un ejemplo de esto es cambiar automáticamente entre bibliotecas en los directorios prod / uat / dev, con la recolección de la biblioteca en cascada en prod si falta en dev y / o UAT (la última condición hace que la solución estándar "use lib + FindBin" sea bastante complicada). ilustración detallada de este escenario es en ¿Cómo puedo utilizar módulos Perl beta desde scripts de Perl beta? .

  • Un caso de uso adicional para la manipulación directa @INCes poder agregar referencias de subrutina o referencias de objeto (sí, Virginia, @INCpuede contener código Perl personalizado y no solo nombres de directorio, como se explica en ¿ Cuándo se llama una referencia de subrutina en @INC? ).

DVK
fuente
1
no olvides PERLOPT, donde puedes configurar -I. Además, cosas como base.pm y local :: lib usan las cosas que ha enumerado implícitamente.
brian d foy
1
@brian - use :: base lo usa debido a "requerir" debajo, IIRC. No estoy familiarizado con local :: lib, necesitaré leer más para entender de qué se trata
DVK
3
Además, para que esta sea una respuesta realmente buena, debe informar a las personas cuándo deben usar cada una. Simplemente darles 10 opciones sobre cómo podrían no es muy útil. :)
brian d foy
PD Cualquier persona, siéntase libre de editar la respuesta para incluir una segunda inclusión de directorio específica de la arquitectura a través de -I / use lib. Planeé hacerlo yo mismo más tarde, pero necesito desconectarme por ahora.
DVK
@brian: se agregó PERLOPT. Tengo ganas de mencionar base.pm y otros elementos de "cuándo se usa @INC" es más adecuado para las preguntas frecuentes de @ INC / find module files que publiqué y vinculé desde aquí, así que lo puse allí.
DVK
18

Además de las ubicaciones enumeradas anteriormente, la versión OS X de Perl también tiene dos formas más:

  1. El archivo /Library/Perl/x.xx/AppendToPath. Las rutas enumeradas en este archivo se agregan a @INC en tiempo de ejecución.

  2. El archivo /Library/Perl/x.xx/PrependToPath. Las rutas enumeradas en este archivo se anteponen a @INC en tiempo de ejecución.

dgatwood
fuente
6

Como ya se dijo, @INC es una matriz y eres libre de agregar lo que quieras.

Mi script CGI REST se ve así:

#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
    push @INC, 'fully_qualified_path_to_module_wiht_our_REST.pm';
}
use Modules::Rest;
gone(@_);

La subrutina desaparecida es exportada por Rest.pm.

Kacper Perschke
fuente