2010-03-26 13 views
13

Si mi programa Perl usa módulos Perl, ¿cómo determinará dónde encontrar el archivo que contiene el código del módulo?¿Cómo sabe un programa Perl dónde encontrar el archivo que contiene el módulo Perl que utiliza?

Por ejemplo, si el programa contiene:

use MyModule1;    # Example 1 
use This::Here::MyModule2; # Example 2 

donde se va a ver?

+0

No pude encontrar una respuesta completa a esta pregunta en SO a la que pudiera vincular, así que decidí crear una. Si la respuesta proporcionada a continuación necesita adiciones/correcciones, por favor tenga en ella :) – DVK

Respuesta

13

El intérprete Perl (que ejecuta su programa perl) utilizará una matriz especial llamada @INC para buscar un archivo que contenga el módulo.

Cada valor en la matriz @INC es un nombre de directorio (pero vea la nota a continuación); Perl buscará dentro de esos directorios en un bucle utilizando las reglas especificadas a continuación. (Por favor, consulte this SO post for details of how the contents of @INC are determined).

Si no se encuentra el archivo del módulo después de agotar @INC, la compilación del programa se cancelará con un error. Si el archivo del módulo se encuentra en uno de los directorios especificados en @INC, la búsqueda finaliza sin mirar el resto de @INC.

La forma en que Perl busca un archivo módulo dentro de cada uno de los directorios listados en @INC es el siguiente:

  • En primer lugar, se separará componentes jerárquicos del nombre del módulo (palabras separadas por ::), en el último componente, que se usará para formar un nombre de archivo, y una ruta de jerarquía (todos los componentes anteriores al último ::).

    En caso de que el nombre del módulo tenga solo un componente (no ::, por ejemplo, MyModule1), la ruta de la jerarquía está vacía y el nombre del archivo es el nombre del módulo. En el segundo ejemplo de esta pregunta, el último componente es MyModule2 y la ruta jerárquica será This::Here.

  • El nombre del archivo esperado se determinará al agregar el último componente del nombre del módulo con una extensión .pm. P.ej. MyModule1.pm y MyModule2.pm en nuestros ejemplos.

    NOTA: Los nombres de los módulos obviamente distinguen entre mayúsculas y minúsculas en Unix y en otros sistemas operativos donde el nombre de archivo/directorio distingue entre mayúsculas y minúsculas.

  • directorio del módulo será determinado por:

    1. Tomando el siguiente directorio de @INC - digamos /usr/lib/perl como ejemplo

    2. La formación de un subdirectorio de ese directorio mediante la adopción de la jerarquía ruta del nombre del módulo (si lo hay) y reemplazando "::" con / o cualquier carácter que el sistema operativo use como separador de directorio. En nuestros dos ejemplos, el primer módulo se buscará en /usr/lib/perl (sin subdirectorio) y el segundo en /usr/lib/perl/This/Here.

    3. NOTA: lo anterior es una ligera simplificación - @INCmay also contain subroutine references and object references, que cargan los módulos como su código personalizado especifica en lugar de realizar la búsqueda en el directorio especificado en el # 2 lógica anterior. Esa funcionalidad parece ser muy poco utilizada y este artículo asume que todo @INC solo contiene directorios.

Repasemos un ejemplo específico, en el supuesto de que su @INC contiene dos subdirectorios: ("/usr/lib/perl", "/opt/custom/lib").

Entonces Perl sería buscar la siguiente manera:

 
========================================================================== 
| Module    | Try # | File to try    
========================================================================== 
| MyModule1    | Try 1 | /usr/lib/perl/MyModule1.pm 
| MyModule1    | Try 2 | /opt/custom/lib/MyModule1.pm 
========================================================================== 
| This::Here::MyModule2 | Try 1 | /usr/lib/perl/This/Here/MyModule2.pm 
| This::Here::MyModule2 | Try 2 | /opt/custom/lib/This/Here/MyModule2.pm 
========================================================================== 

Por favor, recuerde que Perl intérprete dejará de intentar buscar una vez que encuentra el archivo en uno de los lugares, sin tratar de ver si el archivo está en ubicaciones posteriores también. P.ej. si existe /usr/lib/perl/This/Here/MyModule2.pm, entonces Perl no buscará ni le importará la existencia de /opt/custom/lib/This/Here/MyModule2.pm.

NOTA: @INC se usa cuando el intérprete de Perl utiliza el mecanismo similar a require para importar módulos Perl. Esto incluye:

  • require propia directiva
  • use MyModule declaración (equivalente a requerir + importaciones)
  • use base (equivalente a requerir + "empujar @ISA")
+2

Es probable que valga la pena señalar de dónde provienen los contenidos de @INC. Esta puede incluso ser la respuesta que el OP estaba buscando. El breve resumen: los principales contenidos por defecto están incorporados (obviamente, los detalles exactos de las rutas dependen de su instalación). Las formas principales de modificarlo fuera del script son establecer la variable de entorno PERL5LIB (una lista de rutas delimitada por dos puntos) o suministrar las opciones '-I/path/to/dir' al ejecutable en tiempo de ejecución. (Estos preceden a la matriz) – Cascabel

+0

¿Alguien tiene una buena lista de cómo exactamente se construye @INC? El que está en perldoc perlvar parece estar omitiendo cualquier mención de PERL5LIB, así como el mecanismo '$ Config {sitelib}/sitecustomize.pl' (que tiene que incorporarse en tiempo de compilación). – Cascabel

+0

@DVK: ¡excelente! Erróneamente asumió que había terminado por el comentario a la pregunta y el hecho de que esto ya es increíblemente minucioso. – Cascabel

2

De acuerdo con la perlfunc documentation on use:

use Module LI ST

Importa algunas semánticas en el paquete actual desde el módulo nombrado, generalmente aliasing cierta subrutina o nombres de variables en su paquete. Es exactamente equivalente a

BEGIN { require Module; Module->import(LIST); } 

excepto que el Módulo debe ser una palabra clave.

Así require hace el trabajo pesado, y el require documentation proporciona

si expr es un bareword, la requieren asume una extensión ".pm" y reemplaza "::" con "/" en el nombre de archivo para usted, para hacer más fácil para cargar módulos estándar. Esta forma de carga de módulos no corre el riesgo de alterar su espacio de nombres.

En otras palabras, si usted intenta esto:

require Foo::Bar; # a splendid bareword 

La función requiere realmente buscará el archivo "Foo/Bar.pm" en los directorios especificados en la matriz @INC.

5

Si bien esto no responde directamente la pregunta, aquí hay algunas técnicas simples para determinar la ruta completa al archivo de módulo que desea utilizar.

Para ver el contenido predeterminado de la matriz @INC, junto con un montón de otra información, desde la línea de comandos:

perl -V  

Si desea conocer la ubicación del módulo Carp:

perldoc -l Carp 

Dentro de un script, imprimir el contenido del hash %INC es útil para determinar el módulo real que está utilizando, especialmente si ha modificado @INC de su valor predeterminado:

use Carp; 
print $INC{'Carp.pm'}; 

Este script simple también se puede usar para Find installed Perl modules matching a regular expression e identificar cualquier módulo duplicado en directorios diferentes.

+0

@toolic - esta respuesta está estrechamente relacionada con la Pregunta de OP, pero creo que está algo separado de ella (por ejemplo, "de dónde viene el módulo que importé"). ¿Le importaría publicarlo como una Q + A separada en SO (lo vincularé), o darme su consentimiento para solicitarlo como una Q por separado y publicar su respuesta (o dejar que vuelva a publicar la suya)? – DVK

+0

hecho! http://stackoverflow.com/questions/2527990/how-do-i-find-which-file-contains-perl-module-my-script-uses – DVK

+0

@DVK - Si tengo dos versiones de Perl en mi ruta de Windows variable de entorno, ¿cómo sabe el sistema qué perl elegir? ¿Es el primero? Tengo diferentes perls para diferentes programas instalados en mi máquina. Fueron instalados junto con el software. – stack1

Cuestiones relacionadas