Как я могу использовать модуль 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';
}