Как «использовать» модуль Perl в каталоге, а не в @INC?

46

У меня есть модуль в родительском каталоге моего script, и я хотел бы использовать его.

Если я делаю

use '../Foo.pm';

Я получаю синтаксические ошибки.

Я попытался сделать:

push @INC, '..';
use EPMS;

и.., по-видимому, не отображается в @INC

Я схожу с ума! Что здесь не так?

Теги:
module
use
relative-path

6 ответов

77
Лучший ответ

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
    Обычно вы хотите сделать unshift, чтобы ваш каталог находился в начале списка. Таким образом, Perl не нужно искать все @INC, чтобы найти его. :)
  • 0
    Да, все верно, и поэтому use lib преобразования BEGIN {push} => use lib не является идентичным. Но я хотел показать минимальное полезное изменение от вопроса, чтобы оно заработало. Спасибо, что заметили :)
Показать ещё 2 комментария
19

Существует несколько способов изменения @INC.

  • установить PERL5LIB, как описано в perlrun

  • используйте ключ -I в командной строке, также задокументированный в perlrun. Вы также можете применить это автоматически с помощью PERL5OPT, но просто используйте PERL5LIB, если вы это сделаете.

  • use lib внутри вашей программы, хотя это хрупко, поскольку другой человек на другой машине может иметь его в другом каталоге.

  • Вручную измените @INC, убедившись, что вы делаете это во время компиляции, если хотите использовать модуль с использованием. Это слишком много работает.

11

Лично я предпочитаю хранить свои модули (те, которые я пишу для себя или для систем, которые я могу контролировать) в определенном каталоге, а также размещать их в подкаталоге. Как в:

/www/modules/MyMods/Foo.pm
/www/modules/MyMods/Bar.pm

И затем, где я их использую:

use lib qw(/www/modules);
use MyMods::Foo;
use MyMods::Bar;

В стороне.. когда дело доходит до нажатия, я предпочитаю запятую с жирными стрелками:

push @array => $pushee;

Но это только вопрос предпочтения.

  • 2
    Этот толкающий синтаксис выглядит очень запутанным. Это определенно указывает неправильный путь. С механической точки зрения. Это так же, как запятая? Запятая гораздо двусмысленнее в отношении направления, и, следовательно, лучше ...
  • 0
    @StevenLu От perldoc perlop : «Оператор => является синонимом запятой, за исключением того, что он вызывает слово слева от него, которое интерпретируется как строка, если оно начинается с буквы или подчеркивания и состоит только из букв, цифр и подчеркиваний . [...] В противном случае оператор => ведет себя точно так же, как оператор запятой или разделитель аргументов списка, в зависимости от контекста. " => также известен как «толстая запятая».
Показать ещё 1 комментарий
6

'use lib' - это ответ, как упоминалось ранее. Еще один вариант - использовать require/import вместо использования. Это означает, что модуль не будет загружаться во время компиляции, а вместо этого во время выполнения.

Это позволит вам изменить @INC по мере того, как вы там пытались, или вы можете передать требуемый путь к файлу вместо имени модуля. Из "perldoc -f require":

Если EXPR - это годовое слово, требование предполагает расширение ".pm" и заменяет "::" на "/" в имени файла для вас, чтобы упростить загрузить стандартные модули. Эта форма загрузки модулей не подвержена риску изменяя пространство имен.

2

Вы должны обработать push до того, как use - и use обрабатывается раньше. Итак, вам понадобится BEGIN { push @INC, ".."; }, чтобы иметь шанс, я полагаю.

  • 1
    Обычно вы хотите сделать unshift, чтобы ваш каталог находился в начале списка. Таким образом, Perl не нужно искать все @INC, чтобы найти его. :)
  • 0
    Да, это тоже ... Я обычно не использую относительные имена, потому что я обычно не запускаю скрипты из фиксированного каталога, так что ...
1

Как указано в "perldoc -f use":

Это точно эквивалентно BEGIN { require Module; import Module LIST; }
за исключением того, что модуль должен быть гостем.

Другими словами, "использование" эквивалентно:

  • работает во время компиляции,
  • преобразование имени пакета в имя файла,
  • require - имя этого файла и
  • import -показать этот пакет.

Итак, вместо вызова использования вы можете вызвать require и импортировать внутри блока BEGIN:

BEGIN {
  require '../EPMS.pm';
  EPMS->import();
}

И, конечно, если ваш модуль на самом деле не выполняет экспорт символов или другую инициализацию при вызове импорта, вы можете оставить эту строку:

BEGIN {
  require '../EPMS.pm';
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню