Как создается Perl @INC? (ака, как все это влияет на поиск модулей Perl?)
Какие есть способы повлиять на поиск модулей Perl? или, как устроен Perl @INC?
Как мы знаем, Perl использует @INC
массив, содержащий имена каталогов, чтобы определить, где искать файлы модуля Perl.
Похоже, что в Stackru нет подробного поста типа "@INC", поэтому этот вопрос задуман как один.
3 ответа
Мы посмотрим, как сконструировано содержимое этого массива, и с его помощью можно влиять на то, где интерпретатор Perl найдет файлы модуля.
По умолчанию
@INC
Perl-интерпретатор компилируется с определенным
@INC
значение по умолчанию. Чтобы узнать это значение, запуститеenv -i perl -V
команда (env -i
игнорируетPERL5LIB
переменная окружения - см. #2) и в результате вы увидите что-то вроде этого:$ env -i perl -V ... @INC: /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 .
Заметка .
в конце; это текущий каталог (который не обязательно совпадает с каталогом скрипта). Это отсутствует в Perl 5.26+, и когда Perl работает с -T
(проверка на заражение включена).
Чтобы изменить путь по умолчанию при настройке бинарной компиляции Perl, установите опцию конфигурации otherlibdirs
:
Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3
Экологическая переменная
PERL5LIB
(или жеPERLLIB
)Perl предварительно ожидает
@INC
со списком каталогов (разделенных двоеточиями), содержащихся вPERL5LIB
(если он не определен,PERLLIB
используется) переменная окружения вашей оболочки. Чтобы увидеть содержание@INC
послеPERL5LIB
а такжеPERLLIB
переменные среды вступили в силу, запуститеperl -V
,$ perl -V ... %ENV: PERL5LIB="/home/myuser/test" @INC: /home/myuser/test /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 .
-I
опция командной строкиPerl предварительно ожидает
@INC
со списком каталогов (разделенных двоеточиями), переданных в качестве значения-I
опция командной строки. Это можно сделать тремя способами, как обычно, с помощью параметров Perl:Передайте это в командной строке:
perl -I /my/moduledir your_script.pl
Передайте его через первую строку (шебанг) вашего скрипта Perl:
#!/usr/local/bin/perl -w -I /my/moduledir
Передать его как часть
PERL5OPT
(или жеPERLOPT
) переменная окружения (см. главу 19.02 в Программирование на Perl)
Пройдите через
lib
прагмаPerl предварительно ожидает
@INC
со списком каталогов, переданных ему черезuse lib
,В программе:
use lib ("/dir1", "/dir2");
В командной строке:
perl -Mlib=/dir1,/dir2
Вы также можете удалить каталоги из
@INC
с помощьюno lib
,Вы можете напрямую манипулировать
@INC
как обычный массив Perl.Примечание: с
@INC
используется на этапе компиляции, это должно быть сделано внутриBEGIN {}
блок, который предшествуетuse MyModule
заявление.Добавить каталоги в начало через
unshift @INC, $dir
,Добавить каталоги до конца через
push @INC, $dir
,Сделайте что-нибудь еще, что вы можете сделать с массивом Perl.
Примечание: каталоги не перенесены на @INC
в порядке, указанном в этом ответе, например, по умолчанию @INC
последний в списке, которому предшествует PERL5LIB
, предшествует -I
, предшествует use lib
и прямой @INC
манипулирование, последние два смешаны в любом порядке в коде Perl.
Рекомендации:
- perldoc perlmod
- Perldoc Lib
- Perl Module Mechanics - отличное руководство, содержащее практические инструкции
- Как "использовать" модуль Perl в каталоге, а не в
@INC
? - Программирование на Perl - глава 31, часть 13, глава 7.2.41
- Как Perl-программа знает, где найти файл, содержащий модуль Perl, который она использует?
Там не кажется всеобъемлющим @INC
Пост типа FAQ по переполнению стека, поэтому этот вопрос задуман как один.
Когда использовать каждый подход?
Если модули в каталоге должны использоваться многими / всеми сценариями на вашем сайте, особенно выполняемыми несколькими пользователями, этот каталог должен быть включен по умолчанию
@INC
скомпилирован в бинарный файл Perl.Если модули в каталоге будут использоваться исключительно конкретным пользователем для всех сценариев, которые запускает пользователь (или если перекомпиляция Perl не является опцией для изменения по умолчанию
@INC
в предыдущем случае использования), установитеPERL5LIB
, обычно во время входа пользователя.Примечание: Пожалуйста, имейте в виду обычные подводные камни переменных среды Unix - например, в некоторых случаях запуск сценариев от имени конкретного пользователя не гарантирует запуск их с настройкой среды этого пользователя, например, через
su
,Если модули в каталоге необходимо использовать только в определенных обстоятельствах (например, когда сценарии выполняются в режиме разработки / отладки, вы можете установить
PERL5LIB
вручную или передать-I
возможность перл.Если модули необходимо использовать только для определенных сценариев, все пользователи, использующие их, используют
use lib
/no lib
Прагмы в самой программе. Его также следует использовать, когда каталог, который необходимо найти, должен быть динамически определен во время выполнения - например, из параметров командной строки сценария или пути сценария (см. Очень хороший пример использования в модуле FindBin).Если каталоги в
@INC
необходимо манипулировать в соответствии с какой-то сложной логикой, либо невозможно слишком громоздким для реализации с помощью комбинацииuse lib
/no lib
Прагмы, а затем использовать прямой@INC
манипуляции внутриBEGIN {}
блок или внутри специальной библиотеки, предназначенной для@INC
манипуляции, которые должны использоваться вашими скриптами перед использованием любых других модулей.Примером этого является автоматическое переключение между библиотеками в каталогах prod / uat / dev, с водопадной библиотекой в prod, если она отсутствует в dev и / или UAT (последнее условие довольно усложняет стандартное решение "use lib + FindBin". A Подробная иллюстрация этого сценария находится в разделе Как использовать бета-модули Perl из бета-скриптов Perl?
Дополнительный вариант использования для прямого манипулирования
@INC
должен иметь возможность добавлять ссылки на подпрограммы или ссылки на объекты (да, Вирджиния,@INC
может содержать собственный код Perl, а не только имена каталогов, как описано в разделе Когда вызывается ссылка на подпрограмму в @INC?).
В дополнение к местам, перечисленным выше, версия Perl для OS X также имеет еще два способа:
Файл /Library/Perl/x.xx/AppendToPath. Пути, перечисленные в этом файле, добавляются к @INC во время выполнения.
Файл /Library/Perl/x.xx/PrependToPath. Пути, перечисленные в этом файле, добавляются к @INC во время выполнения.
Как уже было сказано, @INC - это массив, и вы можете добавлять все, что захотите.
Мой скрипт CGI REST выглядит так:
#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
push @INC, 'fully_qualified_path_to_module_wiht_our_REST.pm';
}
use Modules::Rest;
gone(@_);
Подпрограмма ушел экспортируется Rest.pm.