Каковы все способы влияния на поиск модулей Perl? или Как создается Perl @INC?
Как известно, Perl использует массив @INC
, содержащий имена каталогов, чтобы определить, где искать файлы модулей Perl.
В StackOverflow не существует подробного сообщения типа "@INC" для часто задаваемых вопросов, поэтому этот вопрос предназначен как один.
Мы рассмотрим, как сконструировано содержимое этого массива, и его можно манипулировать, чтобы повлиять на то, где интерпретатор 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 запускается с -T
(проверки проверки taint).
Чтобы изменить путь по умолчанию при настройке бинарной компиляции 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
Передайте его по первой строке (shebang) вашего Perl script:
#!/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.
@INC
?Кажется, что в Qaru не существует всеобъемлющего сообщения типа @INC
FAQ-типа, поэтому этот вопрос предназначен как один.
Если модули в каталоге должны использоваться многими/всеми скриптами на вашем сайте, особенно для нескольких пользователей, этот каталог должен быть включен в стандартный @INC
, скомпилированный в двоичный файл Perl.
Если модули в каталоге будут использоваться исключительно конкретным пользователем для всех сценариев, которые запускаются пользователем (или если перекомпиляция Perl не является вариантом изменения значения по умолчанию @INC
в предыдущем случае использования), установите пользователей PERL5LIB
, обычно во время входа пользователя.
Примечание. Помните об обычных ошибках переменных среды Unix - например, в некоторых случаях запуск сценариев в качестве конкретного пользователя не гарантирует их запуск с установленной пользовательской средой, например. через su
.
Если модули в каталоге должны использоваться только в определенных обстоятельствах (например, когда script выполняется в режиме разработки/отладки, вы можете либо установить PERL5LIB
вручную, либо передать -I
для perl.
Если модули должны использоваться только для определенных сценариев, всеми пользователями, использующими их, используйте use lib
/no lib
прагмы в самой программе. Он также должен использоваться, когда поиск в каталоге должен быть динамически определен во время выполнения - например, из параметров командной строки script или script path (см. FindBin для очень приятного использования).
Если каталоги в @INC
нужно манипулировать в соответствии с какой-то сложной логикой, либо невозможно слишком громоздко реализовать путем комбинации прагм. use lib
/no lib
, а затем использовать прямую манипуляцию @INC
внутри BEGIN {}
в блоке специального назначения, предназначенном для обработки @INC
, который должен использоваться вашим script (s) до использования любых других модулей.
Примером этого является автоматическое переключение между библиотеками в каталогах prod/uat/dev, с загрузкой библиотеки водопада в prod, если она отсутствует в dev и/или UAT (последнее условие делает стандартное решение use lib + FindBin справедливым сложно. Подробную иллюстрацию этого сценария можно найти в Как использовать бета-модули Perl из бета-скриптов Perl?.
Дополнительным вариантом использования для прямого управления @INC
является возможность добавления ссылок подпрограмм или ссылок на объекты (да, Вирджиния, @INC
может содержать пользовательский код Perl, а не только имена каталогов, как объясняется в Когда ссылка подпрограммы в @INC называется?).
В дополнение к местам, перечисленным выше, версия Perl OS X также имеет еще два способа:
Файл/Library/Perl/x.xx/AppendToPath. Пути, перечисленные в этом файле, добавляются к @INC во время выполнения.
Файл/Library/Perl/x.xx/PrependToPath. Пути, перечисленные в этом файле, добавляются к @INC во время выполнения.
Как уже было сказано, @INC - это массив, и вы можете добавлять все, что хотите.
Мой CGI REST script выглядит так:
#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
push @INC, 'fully_qualified_path_to_module_wiht_our_REST.pm';
}
use Modules::Rest;
gone(@_);
Подпрограмма go экспортируется Rest.pm.
@INC
во время выполнения, а не о полной конструкции.