Как использовать модуль Perl из относительного местоположения?
у меня есть dir называется foo
, и в этом у меня lib
и bin
. Скрипты в bin
нужны вещи в lib
. Я делаю что-то вроде этого:
#!perl
use strict;
use warnings;
use lib '../lib';
use Foo; # <-- comes from lib
но это означает, что я должен быть в bin
dir для запуска сценария. Конечно, есть лучший способ. Как правильно это сделать?
8 ответов
стандартный FindBin
модуль делает то, что вы хотите.
use FindBin;
use lib "$FindBin::Bin/../lib";
perldoc FindBin
дополнительные.
проанализируйте полный путь к вашему .pl
via __FILE__
и и наметываем ../lib
в конце или выскочить последний элемент split(/\//,__FILE__)
и добавить /lib
для этого.
Я обычно использую эту технику. Его печально вдохновил из моих дней PHP:
это удобно в ситуациях, когда вы знаете, где данный файл будет быть относительно текущего и не уверены в точках входа, которые он может быть вызван или в окружающей среде во время вызова.
однако я бы вообще использовал эту технику только для тестовых сценариев, которым нужны фиктивные библиотеки для эмуляции вещей.
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;
в идеале есть должен быть какой-то модуль где-то, что делает это, если нет, я наполовину соблазн написать один:
use Some::Module ();
use lib Some::Module::relative_self('../../lib', __FILE__ );
модуль "FindBin" будет работать только в том случае, если каталог, в котором находится скрипт perl, находится в вашем системном пути, иначе он потерпит неудачу. Преодолеть это вы можете манипулировать значение, чтобы получить информацию о пути к perl-модулю и передать значение в
use lib
.
что-то вроде этого -
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() );
#Replace the bin tag with lib to get module directory
$path =~ s{bin/?$}{lib};
}
use lib $path;
EDIT: Модуль FindBin работает просто отлично и может использоваться, как описано в Майкл. Мой понимание его работы было неполным и поэтому привело меня к первому замечанию, которое я сейчас снимаю. Во всяком случае, я не вижу причин, почему этот метод не должен работать, хотя и с несколькими строками больше, чем может быть достигнуто с помощью FindBin (TMTOWTDI).
чтобы добавить свои собственные два цента в эту коллекцию ответов, я обычно решаю эту проблему, используя что-то вроде следующих строк:
use lib do {
use Cwd 'realpath';
my ($dir) = __FILE__ =~ m{^(.*)/}; # $dir = path of current file
realpath("$dir/../lib"); # path of '../lib' relative to $dir
};
Я люблю do
блок, потому что все необходимое так аккуратно содержится в нем. Если вам когда-либо нужно скопировать/вставить или попытаться понять свой код позже, вам не нужно искать отдельный BEGIN
блок или что-то в этом роде.
приведенный выше код наивно предполагает, что /
используется в качестве dir / filename разделитель.
use lib './';
работал на меня с Perl v5.14.2 в поле linux для включения файлов в тот же каталог, что и мой скрипт.
Возможно, вам удастся переместить каталоги lib и bin в рабочий каталог вашего скрипта и попытаться ссылаться на них с помощью
use lib './bin/';
Как насчет:
BEGIN: {
push @INC, '/full/path/to/lib';
}
чтобы сделать относительную ссылку, предположим, что вы собираетесь сохранить ее в bin dir, поэтому вместо этого вставьте относительную ссылку.