[perl] подключение библиотеки с относительным путем.

Teteshnik

Ситуация обычная. Есть тестовые и боевые библиотеки и скрипты. Отличаются они только конфиг файлом. Соответственно. Все кроме конфиг файла лежит в СВН.
Структура такая
/home/tagan/test/main.pl
/home/tagan/test/LIB/lib1.pm
/home/tagan/test/LIB/lib2.pm
/home/tagan/test/LIB/config.pm
я в файле main хочу подключить LIB.
Делаю use lib 'LIB';.
И теперь получается
/home/tagan/test# ./main.pl - все работает
/home/tagan# ./test/main.pl - ничо не работает
Меня интересует как подключить LIB, без указания абсолютного пути и чтобы работал 2-й вариант.

Marinavo_0507

ну можно использовать путь относительно main.pl

Teteshnik

ну use lib './LIB'; - тоже не помогает.
эээ... так, видимо мне нужно подключить мега библиотеку для определения текущего пути?

tokuchu

Я чего-то такое у себя приписывал в своё время:
if ($0 =~ m%^(.*)/%) { unshift(@INC, $1.'/../lib'); } 
else { unshift(@INC, '../lib'); }

Teteshnik

Угу, спасибо. Я тоже понял, что истина в @INC. буду хелп читать.

Teteshnik

короче хз у меня тока так получилось

use Cwd;

use File::Basename;
BEGIN {
my $dir = dirname($0);
my $path;
if ($dir =~ /^\//) {
#--absolute path
$path = $dir;
} elsif ($dir eq ".") {
#-- relative, current dir
$path = getcwd;
} else {
#-- relative, but not from current dir
$dir =~ s/^\.\///;
$path = getcwd."/$dir";
}
unshift(@INC, $path.'/LIB');
}

Sharp

Так в ссылке же было решение на две строчки:

use FindBin; # where was script installed?
use lib $FindBin::Bin; # use that dir for libs, too

Неужели не заработало?

Teteshnik

Объясни, пожалуйста, чо это значит. Чего там угадывается? Я не понял описание этого.

Sharp

в общем ту конструкцию, что ты изобразил, реализовали в виде модуля.
Ну плюс этот модуль может пройти все симлинки по пути, и сказать в какой директории на самом деле ты находишься. Но это так, бонусный функционал.
http://search.cpan.org/~jesse/perl-5.12.2/lib/FindBin.pm

Teteshnik

Понял, спасибо. Почитаю.

rosali

писать use lib в скриптах это дурной тон, ну кроме автотестов может быть. выставляй переменную PERL5LIB при тестировании и всё. а в продакшн устанавливай всё в нормальные места, в /usr/share/perl5/ (или какая у тебя там ос чтобы все модули были видны всем скриптам.
когда ты пишешь что модуль надо искать относительно скрипта, ты как бы декларируешь что модуль "принадлежит" скрипту, что ты будешь делать когда захочешь использовать модуль из двух скриптов? :confused:

Bibi

от ждал ответа
use lib::abs 'LIB';
http://search.cpan.org/~mons/lib-abs/lib/lib/abs.pm

Sharp

ты как бы декларируешь что модуль "принадлежит" скрипту
а если так оно и есть? это вполне себе может быть специализированное cgi приложение, причем у пользователя может и не быть прав писать в /usr. Да или просто скрипт, который делает свое дело и все. То есть модуль никому больше не нужен, и /usr засорять не хочется.
Откуда такая категоричность во мнении? Я, например, подобные вещи часто практикую, и никакого плохого тона в этом не вижу.

Teteshnik

вобщем я не особо понял о чем вы
Дело в том что
1) тестовых папок -тоже в идеале не одна.
2) хочется при написании в тессте щелкнуть коммит и только. а в проде только апдейт.
3) в идеале прод - это папка с мегаправами. куда я лезть не могу. и апдейт делает мега человек.
4) про lib::abs я чо-то ваще не понял. кажется оно не то что надо.
5) про "принадлежит" тоже не понял. Если есть скрипт main2.pl, то я так же туда подключаю эту библиотеку.
6) тут сложность также в том, что некоторый скрипт main3.pl висит в кроне и пускает main.pl UPD: которому тоже нужна эта библиотека
Вобщем как-то так.

rosali

ну это примерно как хардкодить константы в код против возможности настраивать их снаружи. если в скрипте написано use lib, то чтобы это перенастроить надо исправлять скрипт. удобнее когда такая настройка делается снаружи (PERL5LIB, perl -I, ...).
> у пользователя может и не быть прав писать в /usr
ну это да проблема. с другой стороны не можешь писать в /usr/ положи всё в ~/usr/ или куда там можешь, и опять же пропиши это в PERL5LIB, а не в код скрипта.
в любом случае не вижу причин привязываться к положению исполняемого скрипта. это знаешь как в доисторические времена, когда под досом "программа" это был каталог с exe-шником и всеми нужными библиотеками, и это всё вместе копировалось с машины в случайные места :) а нынче вроде как считается правильнее когда "пакеты" и зависимости между ними. чтобы если пять программ используют один и тот же модуль, то он был бы в единственном экземпляре (это не столько вопрос занимаемого места, сколько удобства исправления ошибок в этом модуле при этом ты мог бы любое подмножество из этих 5-ти программ на конкретную машину установить.
> модуль никому больше не нужен и /usr засорять не хочется
ну там есть же namespace-ы в чем проблема? и вообще вчера не был никому нужен а сегодня стал вдруг нужен, что всё из-за этого переделывать? каждый модуль должен надеяться стать кому-нибудь нужным :)

rosali

> 6) тут сложность также в том, что некоторый скрипт main3.pl висит в кроне и пускает main.pl UPD: которому тоже нужна эта библиотека
если в хроне написать вызывать не просто main3.pl а PERL5LIB=/blah/ main3.pl то ему самому и всем его подпроцессам будут видны модули находящиеся в /blah/

Sharp

имхо, это все-таки зависит от задачи, используемых методов и т.д.
вот ситуация: человек ведет разработку в одном месте, а на продакшн система ставится либо через какой-нить tar, либо на конечном сервере делают какой-нибудь svn/cvs checkout/update/export. В какую директорию все это попадет — непонятно.
Запускать perl с ключами или выставлять ENV там может не получится по разным причинам.
Так что вполне нормальное решение, оценить кривость или прямость можно только зная конкретику, а ее мы не знаем. Конкретно я, даже и не хочу знать :)

rosali

ну да всё правильно, уговорил :)
> Так в ссылке же было решение на две строчки:
> Неужели не заработало?
только там надо

use lib "$FindBin::Bin/LIB";

Barbie29

1)
 
 #/usr/bin/perl -w

BEGIN
{
push @INC, "./blib/arch", "./blib/lib";
}
etc...

2)
#!/usr/bin/perl -w

use strict;
use Glib;
use Gtk2 -init;
use blib; ########################### вот так выызывать
use Pixels;

etc...

где Pixels это самописная библиотека, вобщем см perldoc blib
а FindBin заточен на работу на винде, чтобы скрипт без изменений работал и на юнихах и на винде

Barbie29

ну use lib './LIB'; - тоже не помогает.
эээ... так, видимо мне нужно подключить мега библиотеку для определения текущего пути?
use lib 'тут надо писать абсолютный путь от корня';
а у тебя указан относительный путь, потому и не работает... это ситуация когда нет рутовых прав и все модули лежат в домашней директории и чтобы это обойти существует blib
можно еще require lib делать

Barbie29

from perldoc perlvar
       @INC    The array @INC contains the list of places that the "do EXPR",
"require", or "use" constructs look for their library files.
It initially consists of the arguments to any -I command-line
switches, followed by the default Perl library, probably
/usr/local/lib/perl, followed by ".", to represent the current
directory. ("." will not be appended if taint checks are
enabled, either by "-T" or by "-t".) If you need to modify
this at runtime, you should use the "use lib" pragma to get the
machine-dependent library properly loaded also:

use lib '/mypath/libdir/';
use SomeMod;

You can also insert hooks into the file inclusion system by
putting Perl code directly into @INC. Those hooks may be sub-
routine references, array references or blessed objects. See
"require" in perlfunc for details.

@_ Within a subroutine the array @_ contains the parameters passed
to that subroutine. See perlsub.

%INC The hash %INC contains entries for each filename included via
the "do", "require", or "use" operators. The key is the file-
name you specified (with module names converted to pathnames
and the value is the location of the file found. The "require"
operator uses this hash to determine whether a particular file
has already been included.

If the file was loaded via a hook (e.g. a subroutine reference,
see "require" in perlfunc for a description of these hooks
this hook is by default inserted into %INC in place of a file-
name. Note, however, that the hook may have set the %INC entry
by itself to provide some more specific info.

tokuchu

push @INC, "./blib/arch", "./blib/lib";
Сказали же, что нужен путь относительно скрипта, а не относительно cwd!

Barbie29

Сказали же, что нужен путь относительно скрипта, а не относительно cwd!
не зная положение скрипта путь к библиотеке относительно скрипта вычислить невозможно , если не дает возможность ставить модули провайдер как системные - значит надо все прописывать, иначе работать не будет. вот хоть ты тресни
 

tokuchu

не зная положение скрипта путь к библиотеке относительно скрипта вычислить невозможно
Не зная положение скрипта его и запустить нельзя будет. :grin:

Teteshnik

я не знаю что ты имеешь ввиду, но у меня работает так как написал в сообщении с кодом. я бы даже сказал пахает. с новыми ништяками типа FindBin сегодня разбираться буду.
Всем спасиба.
Оставить комментарий
Имя или ник:
Комментарий: