如何在不在@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'; }