Если моя программа Perl использует модули Perl, как она определит, где найти файл, содержащий код модуля?
Например, если программа содержит:
use MyModule1; # Example 1
use This::Here::MyModule2; # Example 2
где это посмотрит?
Интерпретатор Perl (который запускает вашу программу Perl) будет использовать специальный массив с именем @INC
для поиска файла, содержащего модуль.
Каждое значение в массиве @INC
является именем каталога (, но см. Примечание ниже ); Perl будет искать в этих каталогах в цикле, используя правила, указанные ниже. (Пожалуйста, обратитесь к этой публикации SO для получения подробной информации о том, как определяется содержимое @INC ).
Если файл модуля не найден после исчерпания @INC
, компиляция программы будет прервана с ошибкой. Если файл модуля находится в одном из каталогов, указанных в @INC
, поиск завершается без просмотра остальной части @INC
.
Perl ищет файл модуля в каждом из каталогов, перечисленных в @INC
, следующим образом:
Во-первых, он разделяет иерархические компоненты имени модуля (слова, разделенные ::
) в последний компонент, который будет использоваться для формирования имени файла, и путь иерархии (все компоненты, предшествующие последнему ::
).
В случае, если в имени модуля есть только один компонент (нет ::
, например, MyModule1
выше), путь иерархии пуст, а имя файла - это имя модуля. Во втором примере в этом вопросе последним компонентом является MyModule2
, а путь иерархии будет This :: Here
.
Ожидаемое имя файла будет определено путем добавления последнего компонента имени модуля с .pm
добавочный номер. Например. MyModule1.pm
и MyModule2.pm
в наших примерах.
ПРИМЕЧАНИЕ: Имена модулей, очевидно, чувствительны к регистру в Unix и других операционных системах, где в именах файлов / каталогов учитывается регистр.
Каталог модуля будет определяться следующим образом:
Взять следующий каталог из @INC
- скажем, / usr / lib / perl
в качестве примера
Формирование подкаталог этого каталога, взяв иерархический путь имени модуля (если есть) и заменив "::" на /
или любой другой символ, который операционная система использует в качестве разделителя каталогов. В наших двух примерах первый модуль будет искать в / usr / lib / perl
(без подкаталога), а второй - в / usr / lib / perl / This / Here
].
ПРИМЕЧАНИЕ : приведенное выше является небольшим упрощением - @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
параметр командной строки Согласно документации perlfunc на use
:
use Module LIST
Импортирует некоторую семантику в текущую package из названного модуля, как правило, путем добавления в ваш пакет имен определенных подпрограмм или переменных. Это в точности эквивалентно
BEGIN {require Module; Модуль-> импорт (СПИСОК); }
за исключением того, что модуль должен быть голым словом.
Таким образом, require
выполняет тяжелую работу, а require
документация предоставляет
Если EXPR является голым словом, require предполагает
". Pm"
и заменяет"::"
на"/"
в имени файла для вас, чтобы упростить загрузку стандартных модулей. Эта форма загрузки модулей не рискует изменить ваше пространство имен.Другими словами, если вы попробуете это:
require Foo :: Bar; # великолепное простое слово
Функция require будет искать файл
"Foo / Bar.pm"
в каталогах, указанных в массиве@INC
.
Хотя это не дает прямого ответа на вопрос, вот несколько простых методов определения полного пути к файлу модуля, который вы хотите использовать.
Чтобы просмотреть содержимое массива @INC по умолчанию, а также множество другой информации, из командной строки:
perl -V
Если вы хотите узнать местонахождение Carp ] module:
perldoc -l Carp
Внутри скрипта печать содержимого хэша % INC полезна для определения фактического модуля, который вы используете, особенно если вы изменили @INC из его по умолчанию:
use Carp;
print $INC{'Carp.pm'};
Этот простой сценарий также можно использовать для поиска установленных модулей Perl, соответствующих регулярному выражению , и для определения любых повторяющихся модулей в разных каталогах.