Как "использовать" модуль Perl в каталоге, а не в @INC?
У меня есть модуль в родительском каталоге моего скрипта, и я бы хотел его использовать.
Если я сделаю
use '../Foo.pm';
Я получаю синтаксические ошибки.
Я пытался сделать:
push @INC, '..';
use EPMS;
и.. видимо не появляется в @INC
Я схожу с ума! Что здесь не так?
8 ответов
use
происходит во время компиляции, так что это будет работать:
BEGIN {push @INC, '..'}
use EPMS;
Но лучшее решение состоит в том, чтобы use lib
, который является более хорошим способом написания вышеупомянутого:
use lib '..';
use EPMS;
В случае, если вы работаете из другого каталога, использование FindBin
Рекомендовано:
use FindBin; # locate this script
use lib "$FindBin::RealBin/.."; # use the parent directory
use EPMS;
Есть несколько способов изменить @INC
,
установите PERL5LIB, как описано в perlrun
используйте ключ -I в командной строке, также задокументированный в perlrun. Вы также можете применить это автоматически с PERL5OPT, но просто используйте PERL5LIB, если вы собираетесь это сделать.
use lib
внутри вашей программы, хотя это хрупко, поскольку другой человек на другом компьютере может иметь его в другом каталоге.Вручную изменить
@INC
убедитесь, что вы делаете это во время компиляции, если хотите использовать модуль с использованием. Это слишком много работы, хотя.
Лично я предпочитаю хранить свои модули (те, которые я пишу для себя или для систем, которыми я могу управлять) в определенном каталоге, а также размещать их в подкаталоге. Как в:
/www/modules/MyMods/Foo.pm
/www/modules/MyMods/Bar.pm
И тогда, где я их использую:
use lib qw(/www/modules);
use MyMods::Foo;
use MyMods::Bar;
В качестве отступления... когда дело доходит до толчка, я предпочитаю запятую с толстой стрелой:
push @array => $pushee;
Но это просто вопрос предпочтений.
"Использовать lib" - это ответ, как упоминалось ранее @ephemient. Еще один вариант - использовать require/import вместо использования. Это означает, что модуль будет загружаться не во время компиляции, а во время выполнения.
Это позволит вам изменить @INC, как вы пытались там, или вы могли бы указать путь к файлу вместо имени модуля. Из 'perldoc -f require':
Если EXPR - это пустое слово, то для запроса требуется расширение ".pm", и вместо имени "::" в имени файла используется "/", чтобы упростить загрузку стандартных модулей. Эта форма загрузки модулей не рискует изменить ваше пространство имен.
Вы должны иметь push
обрабатывается до use
это - и use
обрабатывается рано. Итак, вам понадобится BEGIN { push @INC, ".."; }
иметь шанс, я верю.
Как сообщает "perldoc -f use":
Это в точности эквивалентно
BEGIN { require Module; import Module LIST; }
за исключением того, что модуль должен быть голым словом.
Другими словами, "использование" эквивалентно:
- работает во время компиляции,
- преобразование имени пакета в имя файла,
require
с этим именем файла иimport
в этом пакете.
Таким образом, вместо вызова use вы можете вызвать require и import внутри блока BEGIN:
BEGIN {
require '../EPMS.pm';
EPMS->import();
}
И, конечно же, если ваш модуль на самом деле не выполняет экспорт символов или другую инициализацию при вызове import, вы можете оставить эту строку вне:
BEGIN {
require '../EPMS.pm';
}
Причина, по которой это не работает, заключается в том, что то, что вы добавляете к
@INC
относится к текущему рабочему каталогу в командной строке, а не к каталогу скрипта.
Например, если вы сейчас находитесь в:
a/b/
И скрипт, который вы запускаете, имеет этот URL:
a/b/modules/tests/test1.pl
BEGIN {
unshift(@INC, "..");
}
Вышеприведенное будет означать, что в результате каталог
a/
скорее, чем
a/b/modules
.
Либо вы должны изменить
..
к
./modules
в вашем коде или сделайте
cd modules/tests
в командной строке перед повторным запуском скрипта.
Некоторые IDE неправильно работают с предпочтительным ответом «использовать библиотеку». Я обнаружил, что 'use lib::relative' работает с моей IDE, WebStorm от JetBrains.