metacpan - ¿Cómo uso un módulo Perl desde una ubicación relativa?
perl mcpan (8)
Analice la ruta completa de su .pl
través de __FILE__
y __FILE__
el ../lib
al final o saque el último elemento de split(////,__FILE__)
y agregue /lib
a eso.
Tengo un directorio llamado foo
, y en eso tengo lib
y bin
. Los scripts en bin
necesitan cosas en lib
. Yo hago algo como esto:
#!perl
use strict;
use warnings;
use lib ''../lib'';
use Foo; # <-- comes from lib
Pero eso significa que tengo que estar en el directorio bin
para ejecutar el script. Sin duda hay una mejor manera. ¿Cuál es la forma correcta de hacer esto?
El módulo estándar FindBin
hace lo que quiere.
use FindBin;
use lib "$FindBin::Bin/../lib";
perldoc FindBin
para más.
Generalmente uso esta técnica. Está tristemente inspirado en mis días de PHP:
Es útil en situaciones en las que se sabe dónde un archivo determinado será relativo al actual, y no está seguro de los puntos de entrada a los que se puede llamar o del entorno que lo rodea en el tiempo de llamada.
Sin embargo, generalmente usaría esta técnica solo para scripts de prueba que necesitan librerías ficticias para emular cosas.
use File::Basename ();
use Cwd ();
my $base_dir;
my $relative_path;
BEGIN {
$realitive_path = ''../../'' # Path to base of project relative to the current file
$base_dir = Cwd::realpath( File::Basename::dirname(__FILE__) .''/'' . $relative_path );
}
use lib "${base_dir}/lib";
use Foo;
Idealmente debería haber algún módulo en alguna parte que haga esto, si no, estoy medio tentado de escribir uno:
use Some::Module ();
use lib Some::Module::relative_self(''../../lib'', __FILE__ );
Mi solución:
use lib substr(__FILE__, 0, rindex (__FILE__, "/"));
Qué tal si:
BEGIN: {
push @INC, ''/full/path/to/lib'';
}
Hacer una referencia relativa supondría que la mantendrá en el directorio bin, por lo tanto, inserte la referencia relativa en su lugar.
Solo para agregar mis propios dos centavos a esta colección de respuestas, generalmente resuelvo este problema usando algo de esta manera:
use lib do {
use Cwd ''realpath'';
my ($dir) = __FILE__ =~ m{^(.*)/}; # $dir = path of current file
realpath("$dir/../lib"); # path of ''../lib'' relative to $dir
};
Me gusta usar un bloque do
porque todo lo que necesita está tan bien contenido en él. Si alguna vez necesitas copiar / pegar, o intentas entender tu código más adelante, no tienes que buscar un bloque BEGIN
diferente ni nada por el estilo.
El código anterior supone ingenuamente que /
se usa como separador dir / nombre de archivo.
El módulo "FindBin" solo funcionará si el directorio en el que reside el script de Perl está en la RUTA del sistema, de lo contrario fallará. Para superar eso , puede manipular el valor de $0
para obtener su información de ruta a módulo perl y pasar el valor para use lib
.
Algo como esto -
BEGIN {
use File::Spec::Functions qw(rel2abs);
use File::Basename qw(dirname);
#Covert the script path to absolute and get its directory name
our $path = dirname( rel2abs($0) );
#Replace the bin tag with lib to get module directory
$path =~ s{bin/?$}{lib};
}
use lib $path;
EDITAR: El módulo FindBin funciona perfectamente y se puede utilizar como se describe en la respuesta de Michael . Mi comprensión de su funcionamiento era incompleta y por eso me llevé a hacer el primer comentario que ahora me retracto. De todos modos, no veo ningún motivo por el que este método no funcione, aunque con algunas líneas más de las que se podrían lograr con FindBin (TMTOWTDI).
use lib ''./'';
ha funcionado para mí con Perl v5.14.2 en un linux box para incluir archivos en el mismo directorio que mi script.
Quizás le resulte útil mover sus directorios lib y bin en el directorio de trabajo de su script e intentar hacer referencia a ellos usando
use lib ''./bin/'';