如何在不在@INC的目录中使用Perl模块?

我在我的脚本的父目录中有一个模块,我想“使用”它。

如果我做

use '../Foo.pm'; 

我得到语法错误。

我试图做到:

 push @INC, '..'; use EPMS; 

.. ..显然不出现在@INC

我要疯了! 这里有什么问题?

use发生在编译时,所以这将工作:

 BEGIN {push @INC, '..'} use EPMS; 

但更好的解决scheme是use lib ,这是写上述更好的方法:

 use lib '..'; use EPMS; 

如果您从不同的目录运行,build议使用FindBin

 use FindBin; # locate this script use lib "$FindBin::RealBin/.."; # use the parent directory use EPMS; 

有几种方法可以修改@INC

  • 设置PERL5LIB,如perlrun中所述

  • 在命令行上使用-I开关,也logging在perlrun中 。 你也可以用PERL5OPT自动应用这个,但是如果你打算这么做的话,只需要使用PERL5LIB。

  • 在你的程序中use lib ,虽然这是脆弱的,因为在另一台机器上的另一个人可能会在不同的目录中。

  • 手动修改@INC ,确保在编译时如果要使用模块。 虽然这是太多的工作。

就个人而言,我更愿意将我的模块(我为自己编写的模块或我可以控制的系统)保留在某个目录中,并将它们放在一个子目录中。 如:

 /www/modules/MyMods/Foo.pm /www/modules/MyMods/Bar.pm 

然后,我在哪里使用它们:

 use lib qw(/www/modules); use MyMods::Foo; use MyMods::Bar; 

顺便说一句,当推动时,我更喜欢胖箭头逗号:

 push @array => $pushee; 

但这只是一个偏好问题。

'使用lib'就是答案,正如前面提到的@ephemient。 另一个select是使用require / import而不是use。 这意味着模块不会在编译时加载,而是在运行时加载。

这将允许您在那里尝试修改@INC,或者您可以传递一个指向文件的path而不是模块名称。 从'perldoc -f要求':

如果EXPR是一个空白字符,那么require将采用“.pm”扩展名,并用文件名中的“/”replace为“/”,以便加载标准模块。 这种加载模块的风险不会改变你的名字空间。

use之前,必须先处理push ,并尽早处理。 所以,你需要一个BEGIN { push @INC, ".."; } 我相信,有机会。

据“perldoc -f use”报道:

这完全相同
BEGIN { require Module; import Module LIST; }
除了Module必须是一个空白字。

换句话说,“使用”相当于:

  • 在编译时运行,
  • 将包名转换为文件名,
  • require该文件的名称,和
  • import该包。

因此,可以调用require并在BEGIN块内导入,而不是调用use:

 BEGIN { require '../EPMS.pm'; EPMS->import(); } 

当然,如果你的模块实际上没有做任何符号导出或者其他的初始化操作,那么你可以把这行代码保留下来:

 BEGIN { require '../EPMS.pm'; }