Как Perl-программа узнает, где найти файл, содержащий модуль Perl, который она использует?
Если моя Perl-программа использует модули Perl, как она будет определять, где найти файл, содержащий код модуля?
Например, если программа содержит:
use MyModule1; # Example 1
use This::Here::MyModule2; # Example 2
где это будет выглядеть?
3 ответа
Perl-интерпретатор (который запускает вашу Perl-программу) будет использовать специальный массив под названием @INC
искать файл, содержащий модуль.
Каждое значение в @INC
массив - это имя каталога (но см. примечание ниже); Perl будет искать в этих каталогах в цикле, используя правила, указанные ниже. (Пожалуйста, обратитесь к этой публикации, чтобы узнать, как определяется содержание @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 будет искать следующее:
========================================================================== | Модуль | Попробуйте # | Файл попробовать ========================================================================== | MyModule1 | Попробуйте 1 | /usr/lib/perl/MyModule1.pm | MyModule1 | Попробуйте 2 | /opt/custom/lib/MyModule1.pm ========================================================================== | Это:: Здесь::MyModule2 | Попробуйте 1 | /usr/lib/perl/This/Here/MyModule2.pm | Это:: Здесь::MyModule2 | Попробуйте 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
оператор (эквивалентный запросу + импорт)use base
(эквивалентно + + push @ISA)-M
параметр командной строки
Хотя это не дает прямого ответа на вопрос, вот несколько простых приемов для определения полного пути к файлу модуля, который вы хотите использовать.
Чтобы просмотреть содержимое по умолчанию массива @INC, а также много другой информации из командной строки:
perl -V
Если вы хотите узнать местоположение модуля Carp:
perldoc -l Carp
Внутри скрипта печать содержимого хэша %INC полезна для определения фактического модуля, который вы используете, особенно если вы изменили @INC по умолчанию:
use Carp;
print $INC{'Carp.pm'};
Этот простой сценарий также можно использовать для поиска установленных модулей 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
массив.