Ответ 1
Мы рассмотрим, как сконструировано содержимое этого массива, и его можно манипулировать, чтобы повлиять на то, где интерпретатор 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.
Ссылки:
- perldoc perlmod
- perldoc lib
- Механика Perl Module - отличный справочник, содержащий практические HOW-TOs
- Как использовать 'модуль Perl в каталоге не в
@INC
? - Программирование Perl - глава 31 часть 13, ч. 7.2.41
- Как программа Perl знает, где найти файл, содержащий модуль Perl, который он использует?
Кажется, что в 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 называется?).