2009-04-08 10 views
40

Recientemente escribí una nueva secuencia de comandos de Perl para eliminar procesos en función del nombre del proceso/nombre de usuario y la extendí utilizando Classes para poder reutilizar el código de proceso en otros programas. Mi disposición actual es -¿Cómo puede mi script de Perl encontrar su módulo en el mismo directorio?

/home/mutew/src/prod/pskill  <-- Perl script 
/home/mutew/src/prod/Process.pm <-- Package to handle process descriptions 

añadí ~/src/prod en mi variable $ PATH para acceder a la secuencia de comandos desde cualquier lugar. Al ejecutar la secuencia de comandos desde cualquier directorio que no sea el residente, conduce a "No se puede localizar Process.pm en @INC" (lo que es comprensible dado que, aparte de los directorios compartidos en/usr, @INC incluye solo el directorio actual - '.'). Una solución que he estado usando es la directiva lib uso como así -

use lib '/home/mutew/src/prod'; 

pero esto es un problema importante la portabilidad. ¿Alguna solución que también me permita exportar el script a otros sistemas sin y sin cambios?


EDITAR

  1. Elegí respuesta 'depesz' como la correcta debido a su simplicidad y el núcleo uso del módulo.
  2. aunque la respuesta de Brian Foy sugiere otros métodos para lograr lo mismo (TMTOWTDI), su contribución en perlfaq8 hace que esta pregunta sea absolutamente redundante.
+0

tal vez sea solo mi instalación, pero si ambos archivos están en el mismo directorio simplemente "uso FILENAME.pm". Luego "my $ newVar = PACKAGENAME-> new();" para cualquier programacion de objetos –

+0

¡Vaya, esto debería ser mucho más fácil en Perl que esto! Facilite las cosas fáciles, etc. –

Respuesta

42

El enfoque más simple que encontré es usar el módulo FindBin. De esta manera:

use FindBin; 
use lib $FindBin::Bin; 

Generalmente prefiero tener mis scripts proporcionados de tal manera que los programas están en lo/bin, y las bibliotecas están en lo/lib

En estas situaciones uso un poco más complicado enfoque:

use Cwd qw(abs_path); 
use FindBin; 
use lib abs_path("$FindBin::Bin/../lib"); 

llamada la abs_path es hacer que el @INC contiene lo/lib, y no a cualquier bin/lib /../ - es sólo un ligero cambio, pero hace que la lectura de los mensajes de error más fácil.

+3

No olvide que abs_path devuelve el resultado contaminado en modo de contaminación. Debe usar 'use lib (abs_path (" $ FindBin :: Bin /../ lib ") = ~ m {^ (/.*)}) [0];' o simplemente use 'use lib" $ FindBin :: Bin /../ lib ";' porque no hay motivo para canonizar la ruta. –

3

Eche un vistazo a Par::Packer. Crea un ejecutable con todas las dependencias del script incluidas. Hace la distribución fácil. También podría proporcionar a sus usuarios una versión de su módulo que pueda instalarse en sus sistemas. Consulte Module::Starter para obtener una forma fácil de compilar todos los archivos necesarios para realizar una distribución estándar de estilo CPAN.

9

De perlfaq8, que responde "How do I add a directory to my include path (@INC) at runtime?". También hay varias otras respuestas para preguntas sobre este tema.


¿Cómo agrego un directorio a mi ruta de inclusión (@INC) en tiempo de ejecución?

Estas son las formas sugeridas de modificar su ruta de inclusión, incluyendo variables de entorno, interruptores de tiempo de ejecución y las declaraciones de código:

el medio ambiente perllib variables

$ export PERLLIB=/path/to/my/dir 
$ perl program.pl 

el medio ambiente PERL5LIB variables

$ export PERL5LIB=/path/to/my/dir 
$ perl program.pl 

la bandera de línea de comandos perl -Idir

$ perl -I/path/to/my/dir program.pl 

el pragma uso lib:

use lib "$ENV{HOME}/myown_perllib"; 

El último es particularmente útil porque sabe de arquitecturas dependiente de la máquina. El módulo pragmático lib.pm se incluyó por primera vez con la versión 5.002 de Perl.

+0

Leí perlfaq8 más tarde el mismo día y encontré la respuesta que necesitaba en su artículo contribuido. Me pregunto por qué incluiste el segundo método (use Cwd) aunque @INC ya tiene una entrada para el directorio actual - '.' – aks

0

Para convertir enlaces relativos a absoluto y agregar a @INC, normalmente uso ex :: lib. Por supuesto, esto solo es útil si planea mantener idénticas las ubicaciones relativas de la secuencia de comandos y el módulo en todas las máquinas donde planea ejecutar la secuencia de comandos.

38

tengo curiosidad por qué la solución simplista

use File::Basename; 
use lib dirname (__FILE__); 
use SomeModuleLocatedInTheSameDirectoryAsThisPerlScriptOrModule; 

no subió. El módulo FindBin parece tener algunos problemas si el archivo no es el script de Perl principal ejecutable, sino simplemente un módulo Perl no ejecutable. Al menos así es como interpreto el comentario en el documentation. Realmente no lo probé.

Para tener alguna otra ruta relativa a la ubicación de este archivo Perl, hacer algo como

use File::Basename; 
use lib dirname (__FILE__) . "/MyModules"; 
+3

Me gusta mucho este enfoque, solo tuve que usar 'use Cwd qw (abs_path); use lib dirname (abs_path (__ FILE __)); 'para hacer que el script se pueda llamar a través de un enlace simbólico. ¡Aclamaciones! – sdaau

+0

¡Esta es la única respuesta que funcionó –

+0

impresionante! ¡Esto funciona! –

-1

FindBin::libs encontrarán todas sus bibliotecas colocados en lugares razonables relativos a la ruta desde donde se está ejecutando el script.

-1

Simplemente mantenlo simple. No es necesario importar ninguna biblioteca; acaba de enterarse de que su directorio de trabajo actual:

use lib "$ENV{PWD}/relativ_path_own_perllib"; 

Para problemas similares, se puede leer la variable de entorno que le da su información acerca de dónde se encuentra, su directorio personal, las cosas del sistema operativo, y así sucesivamente, con una sola fila de código de programación en el shell-terminal, como:

perl -e 'map { print; print " : ". $ENV{$_}." \n\r"; } sort keys %ENV ' 

No es necesario enlazar algunas bibliotecas; solo use el %ENV-Hash.

+0

'$ ENV {PWD}' no resuelve el problema, al contrario. Devuelve el directorio de trabajo del _ usuario, no la ubicación del script. – pipe

0

Puede hacer que Perl busque en cualquier directorio usando la bandera -I. Aquí, -I significa @INC que es la matriz de rutas en las que perl busca módulos. El uso de -I agrega la ruta dada a la matriz @INC para esta ejecución.

por ejemplo:

perl -I lib bin/script.pl 

donde lib contiene los módulos de E desea utilizar.

sé que esto funciona para Perl 5. No estoy seguro acerca de otras versiones.

Cuestiones relacionadas