Если моя программа Perl использует модули Perl, как определить, где найти файл, содержащий код модуля?
Например, если программа содержит:
use MyModule1; # Example 1
use This::Here::MyModule2; # Example 2
где он будет выглядеть?
Если моя программа 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
сама директиваuse MyModule
(эквивалент require + import)use base
(эквивалентно запросу + "push @ISA" )Хотя это прямо не отвечает на вопрос, вот несколько простых методов для определения полного пути к файлу модуля, который вы хотите использовать.
Чтобы просмотреть содержимое по умолчанию массива @INC вместе с большим количеством другой информации из командной строки:
perl -V
Если вы хотите узнать расположение модуля Carp:
perldoc -l Carp
Внутри script печать содержимого %INC хеша полезна для определения фактического модуля, который вы используете, особенно если вы изменили @INC по умолчанию:
use Carp;
print $INC{'Carp.pm'};
Этот простой script также можно использовать для Найти установленные модули Perl, соответствующие регулярному выражению, и идентифицировать любые дублирующие модули в разных каталогах.
В соответствии с документацией perlfunc на use
:
использовать LIST
Импортирует некоторую семантику в текущий пакет из именованного модуля, как правило, путем наложения определенных подпрограмм или имен переменных в ваш пакет. Это в точности эквивалентно
BEGIN { require Module; Module->import( LIST ); }
за исключением того, что модуль должен быть дельным.
Итак, require
делает тяжелый подъем, а require
документации предоставляет
Если EXPR - это годовое слово, требуется принять расширение
".pm"
и заменяет"::"
на"/"
в имени файла для вас, чтобы упростить загрузку стандартных модулей. Эта форма загрузки модулей не подвержена изменению вашего пространства имен.Другими словами, если вы попробуете это:
require Foo::Bar; # a splendid bareword
Функция require фактически ищет файл
"Foo/Bar.pm"
в каталогах, указанных в массиве@INC
.