в Perl, когда я делаю use <module name> <ver>;
, система находит файл .pm
для библиотеки где-то в пути @INC
.
Есть ли надежный способ загрузки файла?
в Perl, когда я делаю use <module name> <ver>;
, система находит файл .pm
для библиотеки где-то в пути @INC
.
Есть ли надежный способ загрузки файла?
Да, %INC
содержит полный путь, из которого был загружен модуль.
Пример:
$ perl -M'Data::Dump qw(pp)' -e 'pp(\%INC)'
{
"Data/Dump.pm" => "/usr/share/perl5/Data/Dump.pm",
"Exporter.pm" => "/usr/share/perl/5.10/Exporter.pm",
"List/Util.pm" => "/usr/lib/perl/5.10/List/Util.pm",
"Scalar/Util.pm" => "/usr/lib/perl/5.10/Scalar/Util.pm",
"XSLoader.pm" => "/usr/lib/perl/5.10/XSLoader.pm",
"overload.pm" => "/usr/share/perl/5.10/overload.pm",
"strict.pm" => "/usr/share/perl/5.10/strict.pm",
"vars.pm" => "/usr/share/perl/5.10/vars.pm",
"warnings.pm" => "/usr/share/perl/5.10/warnings.pm",
"warnings/register.pm" => "/usr/share/perl/5.10/warnings/register.pm",
}
Если модуль имеет документацию pod, и если вы можете гарантировать, что утилита perldoc в вашей PATH принадлежит к тому же perl, который запускает ваш script, то эта команда часто дает вам фактический найденный файл:
perldoc -l ModuleName
perl -M'LWP '-e' использовать Data:: Dumper; print Dumper\%INC '| grep LWP
Здесь будет указано расположение модуля LWP на диске, а также список модулей, загруженных внутри LWP.
'LWP.pm' => '/usr/lib/perl5/5.10.0/LWP.pm',
'LWP/Protocol.pm' => '/usr/lib/perl5/5.10.0/LWP/Protocol.pm',
'LWP/UserAgent.pm' => '/usr/lib/perl5/5.10.0/LWP/UserAgent.pm',
Вы хотите посмотреть в переменной %INC
, которая записывает имя файла, которое оно загружает, для загружаемых вами библиотек с do
, require
или use
. Подробнее см. perlvar.
В CPAN имеется большое количество модулей для поиска этой информации, наиболее вероятными кандидатами являются Module:: Find, Module:: Which и Module:: Locate. Я бы, вероятно, пошел с Module:: Locate:
use strict;
use warnings;
use Module::Locate qw/locate/;
my $to_find = "Some::Module";
print "Perl would use: ", scalar locate($to_find), "\n";
В контексте списка locate возвращает все найденные копии Some:: Module в порядке, основанном на @INC.
Изменить: derobert предлагает гораздо лучший способ, я не понимал, что% INC уже имеет это... Это решение на основе модулей все равно было бы полезно, если бы вы хотели знать, прежде чем загружать модуль, из которого он будет загружен.
Вот однострочный (с bash оберткой), чтобы определить, установлен ли модуль, и где он будет загружен из:
#!/bin/bash
perl -M${1} -le "\$mname=\"${1}.pm\";\$mname=~s#::#/#g;print \"$1 INSTALLED AT \$INC{\$mname}\";" 2>/dev/null || echo "${1} NOT INSTALLED"
Назовите его синтаксисом имени модуля perl:
./find_perl_module Font::Metrics::Courier
Из того, что я нашел, perl будет выглядеть в каталогах внутри пути:
perl -le 'print foreach @INC'
Затем он будет выглядеть в стандартной библиотеке, а затем в текущем каталоге.
Это дает вам порядок поиска.
Мой источник:
Module:: Mapper предоставляет способ для навигации по дереву @INC для поиска модулей:
perl -MModule::Mapper -MData::Dumper \
-e 'print Dumper( find_sources( UseINC => 1, Modules => [ @ARGV ] ) )' \
list-of-modules-to-locate
Вы можете использовать команду instmodsh: http://perldoc.perl.org/instmodsh.html.
Я использую оболочку script/usr/local/bin/which_perl_module
#!/bin/sh
if [ ! $1 ];then echo "Which perl module should I look for?"; exit; fi
echo -n "You are using: "
perldoc -l $1
echo "which I found by looking in:"
perl -MData::Dump=pp -e 'unshift @INC, '$1'; pp(\@INC)'