Как программа Perl знает, где найти файл, содержащий модуль Perl, это использует?

Если моя программа Perl использует модули Perl, как она определит, где найти файл, содержащий код модуля?

Например, если программа содержит:

use MyModule1;              # Example 1
use This::Here::MyModule2;  # Example 2

где это посмотрит?

13
задан DVK 26 March 2010 в 20:28
поделиться

3 ответа

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

Каждое значение в массиве @INC является именем каталога (, но см. Примечание ниже ); Perl будет искать в этих каталогах в цикле, используя правила, указанные ниже. (Пожалуйста, обратитесь к этой публикации SO для получения подробной информации о том, как определяется содержимое @INC ).

Если файл модуля не найден после исчерпания @INC , компиляция программы будет прервана с ошибкой. Если файл модуля находится в одном из каталогов, указанных в @INC , поиск завершается без просмотра остальной части @INC .

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

  • Во-первых, он разделяет иерархические компоненты имени модуля (слова, разделенные :: ) в последний компонент, который будет использоваться для формирования имени файла, и путь иерархии (все компоненты, предшествующие последнему :: ).

    В случае, если в имени модуля есть только один компонент (нет :: , например, MyModule1 выше), путь иерархии пуст, а имя файла - это имя модуля. Во втором примере в этом вопросе последним компонентом является MyModule2 , а путь иерархии будет This :: Here .

  • Ожидаемое имя файла будет определено путем добавления последнего компонента имени модуля с .pm добавочный номер. Например. MyModule1.pm и MyModule2.pm в наших примерах.

    ПРИМЕЧАНИЕ: Имена модулей, очевидно, чувствительны к регистру в Unix и других операционных системах, где в именах файлов / каталогов учитывается регистр.

  • Каталог модуля будет определяться следующим образом:

    1. Взять следующий каталог из @INC - скажем, / usr / lib / perl в качестве примера

    2. Формирование подкаталог этого каталога, взяв иерархический путь имени модуля (если есть) и заменив "::" на / или любой другой символ, который операционная система использует в качестве разделителя каталогов. В наших двух примерах первый модуль будет искать в / usr / lib / perl (без подкаталога), а второй - в / usr / lib / perl / This / Here ].

    3. ПРИМЕЧАНИЕ : приведенное выше является небольшим упрощением - @INC может также содержать ссылки на подпрограммы и ссылки на объекты , которые загружают модули, как указано в их пользовательском коде, вместо выполнения поиска в каталог, как указано в логике №2 выше. Эта функция, по-видимому, используется очень редко, и в этой статье предполагается, что весь @INC содержит только каталоги.

Давайте рассмотрим конкретный пример, предполагая, что ваш @INC содержит два подкаталога: ("/ usr / lib / perl", "/ opt / custom / lib ") .

Затем Perl будет искать следующим образом:

==========================================================================
| Module                | Try # | File to try               
==========================================================================
| MyModule1             | Try 1 | /usr/lib/perl/MyModule1.pm
| MyModule1             | Try 2 | /opt/custom/lib/MyModule1.pm
==========================================================================
| This::Here::MyModule2 | Try 1 | /usr/lib/perl/This/Here/MyModule2.pm
| This::Here::MyModule2 | Try 2 | /opt/custom/lib/This/Here/MyModule2.pm
==========================================================================

Пожалуйста, помните, что интерпретатор Perl прекратит попытки поиска, как только найдет файл в одном из мест, не пытаясь увидеть, находится ли файл в более поздних местах.Например. если существует /usr/lib/perl/This/Here/MyModule2.pm , то Perl не будет искать и не заботиться о существовании / opt / custom / lib / This / Here /MyModule2.pm.

ПРИМЕЧАНИЕ: @INC используется всякий раз, когда интерпретатор Perl использует require -подобный механизм для импорта модулей Perl. Это включает в себя:

  • директиву require
  • используйте оператор MyModule (эквивалентно require + import)
  • используйте base (эквивалентно require + "push @ISA")
  • - M параметр командной строки
13
ответ дан 1 December 2019 в 22:57
поделиться

Согласно документации perlfunc на use :

use Module LIST

Импортирует некоторую семантику в текущую package из названного модуля, как правило, путем добавления в ваш пакет имен определенных подпрограмм или переменных. Это в точности эквивалентно

 BEGIN {require Module; Модуль-> импорт (СПИСОК); } 
 

за исключением того, что модуль должен быть голым словом.

Таким образом, require выполняет тяжелую работу, а require документация предоставляет

Если EXPR является голым словом, require предполагает ". Pm" и заменяет "::" на "/" в имени файла для вас, чтобы упростить загрузку стандартных модулей. Эта форма загрузки модулей не рискует изменить ваше пространство имен.

Другими словами, если вы попробуете это:

  require Foo :: Bar; # великолепное простое слово 
 

Функция require будет искать файл "Foo / Bar.pm" в каталогах, указанных в массиве @INC .

2
ответ дан 1 December 2019 в 22:57
поделиться

Хотя это не дает прямого ответа на вопрос, вот несколько простых методов определения полного пути к файлу модуля, который вы хотите использовать.

Чтобы просмотреть содержимое массива @INC по умолчанию, а также множество другой информации, из командной строки:

perl -V      

Если вы хотите узнать местонахождение Carp ] module:

perldoc -l Carp

Внутри скрипта печать содержимого хэша % INC полезна для определения фактического модуля, который вы используете, особенно если вы изменили @INC из его по умолчанию:

use Carp;
print $INC{'Carp.pm'};

Этот простой сценарий также можно использовать для поиска установленных модулей Perl, соответствующих регулярному выражению , и для определения любых повторяющихся модулей в разных каталогах.

5
ответ дан 1 December 2019 в 22:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: