Как "использовать" модуль 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.

см. POD для lib::relative

Другие вопросы по тегам