如何相对于模块路径加载文件?

10

我不知道如何在Perl中完成一个任务,感觉自己做错了什么基本的事情。

我正在做一个较大的项目,所以我将任务分成不同的模块。我将这些模块放入项目目录中的"modules/"子目录中,并将该目录添加到PERL5LIB和PERLLIB中。

所有这些模块都使用一些配置,保存在主项目目录中的外部文件中 - 如果从模块文件的角度看,它位于"../configure.yaml"。

但是,现在当我通过"use"使用模块时,模块中的所有相对路径都被视为来自使用这些模块的脚本的当前目录,而不是来自模块本身的目录。即使我使用FindBin或其他任何东西也不行。

我如何加载一个文件,从模块路径相对呢?这是否可能 / 明智?

4个回答

14

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 的键是基于将 :: 严格转换为 / 并追加 .pm,即使在 Windows、VMS 等平台上也是如此。

请注意,如果在 @INC 中使用相对目录,则 %INC 中的值可能相对于当前目录。因此,在 require/use 和检查 %INC 之间更改目录时要小心。


8

有一个叫做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!

8
全局%INC表包含每个模块的条目,这些模块您已经使用 userequire,并与 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认为从哪里加载文件。


2
我不认为我的程序有BUG - 我只是不知道怎么写 :) 如果我只是在模块中写入,例如 LoadFile("../configure.yaml"); ,并且我在其他地方使用该模块的脚本,Perl 将其作为相对路径从脚本文件而非模块文件使用。要求或调试并没有真正帮助,我知道问题出在哪里,但我不知道该怎么处理它。 - Karel Bílek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接