Как загрузить файл относительно пути к модулю?
Я не знаю, как сделать что-то в Perl, и я чувствую, что делаю что-то принципиально неправильное.
Я делаю большой проект, поэтому я разбил задачу на разные модули. Я поместил модули в каталог проекта, в поддиректорию "modules/" и добавил этот каталог в PERL5LIB и PERLLIB.
Все эти модули используют некоторую конфигурацию, сохраненную во внешнем файле в главной директории проекта - "../configure.yaml", если вы посмотрите на нее с точки зрения файла модуля.
Но сейчас, когда я использую модуль через "использование", все относительные пути в модуле берутся из текущего каталога script с использованием этих модулей, а не из каталога самого модуля. Даже когда я использую FindBin или что-то еще.
Как загрузить файл, относительно пути к модулю? Это даже возможно/целесообразно?
Ответы
Ответ 1
Perl хранит, где модули загружаются из хеша% INC. Вы можете загружать вещи относительно этого:
package Module::Foo;
use File::Spec;
use strict;
use warnings;
my ($volume, $directory) = File::Spec->splitpath( $INC{'Module/Foo.pm'} );
my $config_file = File::Spec->catpath( $volume, $directory, '../configure.yaml' );
% Ключи INC основаны на строгом переводе:: to/with.pm, добавленном, даже на
Windows, VMS и т.д.
Обратите внимание, что значения в% INC могут относиться к текущему каталогу, если вы помещаете относительные каталоги в @INC, поэтому будьте осторожны, если вы меняете каталоги между требованием/использованием и проверкой% INC.
Ответ 2
Там существует модуль, называемый File::ShareDir, который существует для решения этой проблемы. Вы были на правильном пути, пытаясь найти FindBin, но FindBin всегда находит запущенную программу, а не модуль, который ее использует. ShareDir делает что-то очень похожее на решение ysth, за исключением завершенного в приятном интерфейсе.
Использование так же просто, как
my $filename = File::ShareDir::module_file(__PACKAGE__,
'my/data.txt');
# and then open $filename or whatever else.
или
my $dirname = File::ShareDir::module_dir(__PACKAGE__);
# Play ball!
Ответ 3
Глобальная таблица %INC
содержит запись для каждого модуля, у которого есть use
'd или require
' d, связанного с местом, в котором Perl нашел этот модуль.
use YAML;
print $INC{"YAML.pm"};
>> /usr/lib/perl5/site_perl/5.8/YAML.pm
Это более полезно?
Ответ 4
Измените вызов use Module
на require Module
(или require Module; Module->import(LIST)
). Затем используйте отладчик, чтобы пройти процесс загрузки модуля и посмотреть, как Perl считает, что он загружает файлы.