Як будується @INC Perl? (ака. Які всі способи впливати на пошук модулів Perl?)


199

Які всі способи впливати на пошук модулів Perl? або, як будується @INC Perl ?

Як ми знаємо, Perl використовує @INCмасив, що містить імена каталогів, щоб визначити, де шукати файли модулів Perl .

Здається, не існує всеосяжної публікації "@INC" у FAQ на StackOverflow, тому це питання призначене як одне.


7
Так, але на search.cpan.org/perldoc/… є ідеально хороший ?
моб

3
@mobrule: Я не думаю, що це десь поруч настільки всеосяжне - це просто розповідає про те, як додати @INCчас виконання, а не повну конструкцію.
Каскабель

2
@mobrule - @Jefromi вгадав правильно - головна проблема з БУДЬ-якою та всіма посиланнями, які я знайшов до цього часу, - відсутність вичерпної інформації про скомпільований за замовчуванням первинний бінарний @INC
DVK

3
Деякі можуть зробити цю відповідь вичерпною, надіславши мені виправлення. Це легко, тому що perlfaq знаходиться в Github. :)
Брайан d foy

1
Ну, "вичерпна інформація про скомпільований за замовчуванням @INC perl binary" полягає в тому, що це той, хто його створив. Якщо ви запитуєте про різні шляхи, які потрапляють туди, то, я думаю, у вас питання інше, ніж те, на яке ви відповіли.
Брайан d foy

Відповіді:


254

Ми розглянемо, як побудовано вміст цього масиву і чи можемо ними маніпулювати впливати на те, де інтерпретатор 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використовується) змінної середовища вашої оболонки. Щоб побачити зміст змінних @INCafter 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через viano lib .

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

    Примітка: Оскільки @INCвикористовується на етапі компіляції, це потрібно зробити всередині BEGIN {}блоку, який передує use MyModuleоператору.

    • Додайте каталоги до початку через unshift @INC, $dir.

    • Додайте каталоги до кінця через push @INC, $dir.

    • Робіть все, що ви можете зробити з масивом Perl.

Примітка: каталоги зрушать на @INCв порядку , зазначеному в цій відповіді, наприклад , по замовчуванням @INCє останнім у списку, з яким передує PERL5LIB, передує -I, передують use libі прямий @INCманіпуляції, останні два змішуватися в залежності від того , замовити їх в коді Perl.

Список літератури:

Здається, не існує всеосяжної @INCпублікації типу поширених запитань про Stack Overflow, тому це питання призначене як одне.

Коли використовувати кожен підхід?

  • Якщо модулі в каталозі потребують використання багатьох / всіх скриптів на вашому веб-сайті, особливо під керуванням декількох користувачів, цей каталог повинен бути включений до типового @INCзбору у бінарний файл Perl.

  • Якщо модулі в каталозі будуть використовуватися виключно певним користувачем для всіх сценаріїв, якими користувач запускає (або якщо перекомпіляція Perl не є можливістю змінити типовий режим @INCу попередньому випадку використання), встановіть користувача PERL5LIB, як правило, під час входу в систему.

    Примітка. Будь ласка, пам’ятайте про звичні підводні камені змінної середовища Unix - наприклад, у деяких випадках запуск сценаріїв як певний користувач не гарантує запуск їх із налаштованим середовищем цього користувача, наприклад через su.

  • Якщо модулі в каталозі потрібно використовувати лише в конкретних обставинах (наприклад, коли сценарій (и) виконуються в режимі розробки / налагодження, ви можете встановити його PERL5LIBвручну або передати -Iпараметр perl.

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

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

    Прикладом цього є автоматичне перемикання між бібліотеками в каталогах prod / uat / dev, з підхопленням бібліотеки водоспадів у prod, якщо в програмі відсутнє програмне забезпечення dev та / або UAT (остання умова робить стандартне рішення "використання lib + FindBin" досить складним.) Детальна ілюстрація цього сценарію наведена в розділі Як використовувати модулі бета-Perl із сценаріїв бета-версії Perl ? .

  • Додатковим випадком використання для прямого маніпулювання @INCє можливість додати посилання підпрограми або посилання на об'єкти (так, Вірджинія, @INCможе містити користувацький код Perl, а не лише імена каталогів, як пояснено у розділі Коли називається посилання підпрограми в @INC? ).


1
не забувайте PERLOPT, де ви можете встановити -I. Крім того, такі речі, як base.pm та local :: lib, використовують неявно вказані вами речі.
Брайан d foy

1
@brian - use :: base використовує його через "вимагати" під ним, IIRC. Я не знайомий з місцевим :: lib, мені потрібно буде прочитати більше, щоб зрозуміти, про що йдеться
DVK

3
Крім того, щоб зробити це справді гарною відповіддю, потрібно сказати людям, коли вони повинні використовувати кожну. Просто дати їм 10 варіантів того, як вони могли, не дуже корисно. :)
Брайан d foy

PS Будь-хто, будь ласка, змініть відповідь, щоб включити друге включення до каталогу архітектури через -I / use lib. Я планував зробити це самостійно пізніше, але зараз потрібно перейти в офлайн.
DVK

@brian - додав PERLOPT. Мені здається, що згадка про base.pm та інші пункти "коли @INC звикає" більше підходить до файлів модулів @ INC / пошуку модулів, які я часто розміщувала та зв'язала звідси, тому я розмістила його там.
DVK

18

Окрім перелічених вище місць, версія Perl OS X також має ще два способи:

  1. Файл /Library/Perl/x.xx/AppendToPath. Шляхи, перелічені в цьому файлі, додаються до @INC під час виконання.

  2. Файл /Library/Perl/x.xx/PrependToPath. Шляхи, перелічені в цьому файлі, є підготовленими до @INC під час виконання.


6

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.