我的脚本的父目录中有一个模块,我想“使用”它。
如果我做
use '../Foo.pm';
我收到语法错误。
我试着做:
push @INC, '..';
use EPMS;
和..显然没有出现在@INC
我要疯了!这里有什么问题?
我的脚本的父目录中有一个模块,我想“使用”它。
如果我做
use '../Foo.pm';
我收到语法错误。
我试着做:
push @INC, '..';
use EPMS;
和..显然没有出现在@INC
我要疯了!这里有什么问题?
use
发生在编译时,所以这会起作用:
BEGIN {push @INC, '..'}
use EPMS;
但更好的解决方案是use lib
,这是编写上述内容的更好方式:
use lib '..';
use EPMS;
但是,如果您从不同的目录运行,FindBin
建议使用:
use FindBin; # locate this script
use lib "$FindBin::RealBin/.."; # use the parent directory
use EPMS;
您可以通过多种方式修改@INC
.
set PERL5LIB
,如perlrun中所述
使用-I
命令行上的开关,也记录在perlrun中。您也可以使用 PERL5OPT 自动应用它,但如果您要这样做,只需使用 PERL5LIB。
use lib
在你的程序中,虽然这很脆弱,因为不同机器上的另一个人可能将它放在不同的目录中。
手动修改@INC
,确保在编译时这样做,如果你想使用一个模块。不过这工作量太大了。
require
直接文件名。虽然这是可能的,但它不允许该文件名加载同一目录中的文件。这肯定会在代码审查中引起注意。
就个人而言,我更喜欢将我的模块(我为自己或我可以控制的系统编写的模块)保存在某个目录中,并将它们放在子目录中。如:
/www/modules/MyMods/Foo.pm
/www/modules/MyMods/Bar.pm
然后我在哪里使用它们:
use lib qw(/www/modules);
use MyMods::Foo;
use MyMods::Bar;
顺便说一句..在推动方面,我更喜欢粗箭头逗号:
push @array => $pushee;
但这只是偏好问题。
正如@ehemient 前面提到的,'use lib' 就是答案。另一种选择是使用 require/import 而不是 use。这意味着模块不会在编译时加载,而是在运行时加载。
这将允许您在尝试时修改@INC,或者您可以传递文件的路径而不是模块名称。从“perldoc -f 要求”:
如果 EXPR 是一个裸字,则 require 假定扩展名为“.pm”,并为您将文件名中的“::”替换为“/”,以便于加载标准模块。这种形式的模块加载不会改变您的命名空间。
您必须push
在 is 之前处理use
- 并且use
提前处理。所以,我相信你需要BEGIN { push @INC, ".."; }
一个机会。
正如“perldoc -f use”所报告的:
它完全等同于
BEGIN { require Module; import Module LIST; }
除了 Module 必须是一个裸词。
换句话说,“使用”相当于:
require
-ing 那个文件名,并且import
-ing那个包。因此,您可以在 BEGIN 块中调用 require 和 import,而不是调用 use:
BEGIN {
require '../EPMS.pm';
EPMS->import();
}
当然,如果您的模块在调用 import 时实际上没有进行任何符号导出或其他初始化,则可以省略该行:
BEGIN {
require '../EPMS.pm';
}
某些 IDE 无法与首选答案“use lib”一起正常工作。我发现 'use lib::relative' 适用于我的 IDE,JetBrains 的 WebStorm。
它不起作用的原因是因为您要添加的@INC
内容与命令行中的当前工作目录相关,而不是脚本的目录。
例如,如果您目前在:
a/b/
您正在运行的脚本具有以下 URL:
a/b/modules/tests/test1.pl
BEGIN {
unshift(@INC, "..");
}
以上将意味着..
结果是目录a/
而不是a/b/modules
.
在再次运行脚本之前,您必须在代码中更改..
为或在命令行中执行 a。./modules
cd modules/tests