Как создается Perl @INC? (ака, как все это влияет на поиск модулей Perl?)

Какие есть способы повлиять на поиск модулей Perl? или, как устроен Perl @INC?

Как мы знаем, Perl использует @INC массив, содержащий имена каталогов, чтобы определить, где искать файлы модуля Perl.

Похоже, что в Stackru нет подробного поста типа "@INC", поэтому этот вопрос задуман как один.

3 ответа

Решение

Мы посмотрим, как сконструировано содержимое этого массива, и с его помощью можно влиять на то, где интерпретатор Perl найдет файлы модуля.

  1. По умолчанию @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

  1. Экологическая переменная 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
     .
    
  2. -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)

  3. Пройдите через lib прагма

    Perl предварительно ожидает @INC со списком каталогов, переданных ему через use lib,

    В программе:

    use lib ("/dir1", "/dir2");
    

    В командной строке:

    perl -Mlib=/dir1,/dir2
    

    Вы также можете удалить каталоги из @INC с помощью no lib,

  4. Вы можете напрямую манипулировать @INC как обычный массив Perl.

    Примечание: с @INC используется на этапе компиляции, это должно быть сделано внутри BEGIN {} блок, который предшествует use MyModule заявление.

    • Добавить каталоги в начало через unshift @INC, $dir,

    • Добавить каталоги до конца через push @INC, $dir,

    • Сделайте что-нибудь еще, что вы можете сделать с массивом Perl.

Примечание: каталоги не перенесены на @INC в порядке, указанном в этом ответе, например, по умолчанию @INC последний в списке, которому предшествует PERL5LIB, предшествует -I, предшествует use lib и прямой @INC манипулирование, последние два смешаны в любом порядке в коде 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 также имеет еще два способа:

  1. Файл /Library/Perl/x.xx/AppendToPath. Пути, перечисленные в этом файле, добавляются к @INC во время выполнения.

  2. Файл /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.

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