Как я могу использовать модуль Perl в каталоге, отличном от @INC?
У меня есть модуль в родительском каталоге моего script, и я хотел бы использовать его.
Если я делаю
use '../Foo.pm';
Я получаю синтаксические ошибки.
Я попытался сделать:
push @INC, '..';
use EPMS;
и.., по-видимому, не отображается в @INC
Я схожу с ума! Что здесь не так?
Ответы
Ответ 1
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;
Ответ 2
Существует несколько способов изменения @INC
.
-
установить PERL5LIB, как описано в perlrun
-
используйте ключ -I в командной строке, также задокументированный в perlrun. Вы также можете применить это автоматически с помощью PERL5OPT, но просто используйте PERL5LIB, если вы это сделаете.
-
use lib
внутри вашей программы, хотя это хрупко, поскольку другой человек на другой машине может иметь его в другом каталоге.
-
Вручную измените @INC
, убедившись, что вы делаете это во время компиляции, если хотите использовать модуль с использованием. Это слишком много работает.
Ответ 3
Лично я предпочитаю хранить свои модули (те, которые я пишу для себя или для систем, которые я могу контролировать) в определенном каталоге, а также размещать их в подкаталоге. Как в:
/www/modules/MyMods/Foo.pm
/www/modules/MyMods/Bar.pm
И затем, где я их использую:
use lib qw(/www/modules);
use MyMods::Foo;
use MyMods::Bar;
В стороне.. когда дело доходит до нажатия, я предпочитаю запятую с жирными стрелками:
push @array => $pushee;
Но это только вопрос предпочтения.
Ответ 4
'use lib' - это ответ, как упоминалось ранее. Еще один вариант - использовать require/import вместо использования. Это означает, что модуль не будет загружаться во время компиляции, а вместо этого во время выполнения.
Это позволит вам изменить @INC по мере того, как вы там пытались, или вы можете передать требуемый путь к файлу вместо имени модуля. Из "perldoc -f require":
Если EXPR - это годовое слово, требование предполагает расширение ".pm" и заменяет "::" на "/" в имени файла для вас, чтобы упростить загрузить стандартные модули. Эта форма загрузки модулей не подвержена риску изменяя пространство имен.
Ответ 5
Вы должны обработать push
до того, как use
- и use
обрабатывается раньше. Итак, вам понадобится BEGIN { push @INC, ".."; }
, чтобы иметь шанс, я полагаю.
Ответ 6
Как указано в "perldoc -f use":
Это точно эквивалентно BEGIN { require Module; import Module LIST; }
за исключением того, что модуль должен быть гостем.
Другими словами, "использование" эквивалентно:
- работает во время компиляции,
- преобразование имени пакета в имя файла,
-
require
- имя этого файла и
-
import
-показать этот пакет.
Итак, вместо вызова использования вы можете вызвать require и импортировать внутри блока BEGIN:
BEGIN {
require '../EPMS.pm';
EPMS->import();
}
И, конечно, если ваш модуль на самом деле не выполняет экспорт символов или другую инициализацию при вызове импорта, вы можете оставить эту строку:
BEGIN {
require '../EPMS.pm';
}