Как создается Perl @INC? (ака, как все это влияет на поиск модулей Perl?) - PullRequest
198 голосов
/ 27 марта 2010

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

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

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

Ответы [ 3 ]

251 голосов
/ 27 марта 2010

Мы посмотрим, как сконструировано содержимое этого массива, и с его помощью можно повлиять на то, где интерпретатор 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 pragma

    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 опция для perl.

  • Если модули необходимо использовать только для определенных сценариев, всеми пользователями, использующими их, используйте прагмы use lib / no lib в самой программе. Он также должен использоваться, когда каталог, который нужно искать, должен быть динамически определен во время выполнения - например, из параметров командной строки скрипта или пути скрипта (см. очень хороший пример использования в модуле FindBin ).

  • Если каталогами в @INC нужно манипулировать в соответствии с какой-то сложной логикой, которую невозможно или слишком громоздко реализовать с помощью комбинации прагм use lib / no lib, то используйте прямую манипуляцию @INC внутри BEGIN {} блок или внутри специальной библиотеки, предназначенной для манипуляций @INC, которые должны использоваться вашими скриптами перед использованием любых других модулей.

    Примером этого является автоматическое переключение между библиотеками в каталогах prod / uat / dev, с выбором библиотеки водопадов в prod, если он отсутствует в dev и / или UAT (последнее условие делает стандартное решение «use lib + FindBin» справедливым сложно. Подробная иллюстрация этого сценария приведена в Как использовать бета-модули Perl из бета-скриптов Perl? .

  • Дополнительный вариант использования для прямого манипулирования @INC - возможность добавлять ссылки на подпрограммы или ссылки на объекты (да, Вирджиния, @INC может содержать собственный код Perl, а не только имена каталогов, как объяснено в Когда вызывается ссылка на подпрограмму в @INC? ).

17 голосов
/ 31 июля 2012

В дополнение к местам, перечисленным выше, версия Perl для OS X также имеет еще два способа:

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

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

6 голосов
/ 05 мая 2013

Как уже было сказано, @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.

...