如何包含位于不同目录中的 Perl 模块?

Posted

技术标签:

【中文标题】如何包含位于不同目录中的 Perl 模块?【英文标题】:How do I include a Perl module that's in a different directory? 【发布时间】:2010-10-24 21:58:31 【问题描述】:

它必须是包含它的模块的相对路径。

我试过了

push ( @INC,"directory_path/more_path");

还有

push ( @INC,"directory_path\\more_path");

【问题讨论】:

【参考方案1】:

编辑:首先提出正确的解决方案,最初来自 this question。它是唯一一个相对于 module 目录进行搜索的目录:

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

还有许多其他方法可以搜索相对于 当前 目录的库。您可以使用 -I 参数调用 perl,并传递另一个模块的目录:

perl -I.. yourscript.pl

您可以在 perl 脚本顶部附近添加一行:

use lib '..';

您可以在运行脚本之前修改环境变量 PERL5LIB:

export PERL5LIB=$PERL5LIB:..

push(@INC) 策略也可以工作,但它必须被包裹在 BEGIN 中以确保在模块搜索之前运行推送:

BEGIN push @INC, '..'
use yourlib;

【讨论】:

经过多次尝试,最终工作的代码来自 Andomar 链接到的问题:使用 FindBin; # 定位这个脚本使用 lib "$FindBin::Bin/.."; # 使用父目录使用EPMS;谢谢大家的帮助! 干杯,看起来每个人都阅读了“当前目录”,您在其中编写了“模块目录”。 在阅读 ***.com/a/90721/2668831 后发现这个问题,它声称 FindBin 方法对于某些形式的模块化 Perl 组织并不可靠(其他人可能能够澄清)【参考方案2】:

您的推送失败的原因很可能是执行顺序。

use 是编译时指令。你push在执行时完成:

push ( @INC,"directory_path/more_path");
use Foo.pm;  # In directory path/more_path

您可以使用 BEGIN 块来解决此问题:

BEGIN 
    push ( @INC,"directory_path/more_path");

use Foo.pm;  # In directory path/more_path

IMO,它最清楚,因此最好use lib

use lib "directory_path/more_path";
use Foo.pm;  # In directory path/more_path

有关 BEGIN 和其他特殊块以及它们何时执行的信息,请参阅 perlmod。

编辑

对于加载与您的脚本/库相关的代码,我强烈支持File::FindLib

您可以说use File::FindLib 'my/test/libs'; 在路径中脚本上方的任何位置查找库目录。

假设你的工作结构如下:

   /home/me/projects/
    |- shared/
    |   |- bin/
    |   `- lib/
    `- ossum-thing/
       `- scripts 
           |- bin/
           `- lib/

ossum-thing/scripts/bin中的脚本内:

use File::FindLib 'lib/';
use File::FindLib 'shared/lib/';

将找到您的库目录并将它们添加到您的@INC

创建一个包含运行工具套件所需的所有环境设置的模块并将其加载到项目中的所有可执行文件中也很有用。

use File::FindLib 'lib/MyEnvironment.pm'

【讨论】:

【参考方案3】:

'use lib' 也可以采用单个字符串值...

#!/usr/bin/perl
use lib '<relative-path>';
use <your lib>;

【讨论】:

相对路径是什么?【参考方案4】:

来自perlfaq8:


如何将我的程序所在的目录添加到模块/库搜索路径中?

(由布赖恩·德·福伊提供)

如果您已经知道该目录,则可以像添加任何其他目录一样将其添加到@INC。如果您在编译时知道目录,则可以使用 lib:

use lib $directory;

这个任务的诀窍是找到目录。在您的脚本执行任何其他操作(例如 chdir)之前,您可以使用 Perl 附带的 Cwd 模块获取当前工作目录:

BEGIN 
    use Cwd;
    our $directory = cwd;
    

use lib $directory;

您可以使用 $0 的值执行类似的操作,其中包含脚本名称。这可能包含相对路径,但 rel2abs 可以将其转换为绝对路径。一旦你拥有了

BEGIN 
    use File::Spec::Functions qw(rel2abs);
    use File::Basename qw(dirname);

    my $path   = rel2abs( $0 );
    our $directory = dirname( $path );
    

use lib $directory;

Perl 附带的 FindBin 模块可能会起作用。它会找到当前运行脚本的目录并将其放入 $Bin 中,然后您可以使用它来构建正确的库路径:

use FindBin qw($Bin);

【讨论】:

您的第二个建议(在BEGIN 块内使用cwd)似乎不起作用。我得到的只是以下错误:Variable "$directory" is not imported at ./thingy line 16. // Global symbol "$directory" requires explicit package name at ./thingy line 16. // BEGIN not safe after errors--compilation aborted at ./thingy line 16. 你必须给我看你的代码。听起来您可能在导入列表中引用了 $directory。【参考方案5】:

我很惊讶之前没有人提到它,但是FindBin::libs 总是会找到你的库,因为它会在相对于你的脚本位置的所有合理位置进行搜索。

#!/usr/bin/perl
use FindBin::libs;
use <your lib>;

【讨论】:

令我惊讶的是,您的回答 7 年没有得到一个支持。有一个。【参考方案6】:

我会告诉你如何在 eclipse 中完成它。我的开发系统 - Windows 64bit、Eclipse Luna、Eclipse 的 Perlipse 插件、Strawberry Pearl 安装程序。我使用 perl.exe 作为我的解释器。

Eclipse > 创建新的 perl 项目 > 右键单击​​项目 > 构建路径 > 配置构建路径 > 库选项卡 > 添加外部源文件夹 > 转到安装所有 perl 模块的文件夹 > 好的 > 好的。完成!

【讨论】:

以上是关于如何包含位于不同目录中的 Perl 模块?的主要内容,如果未能解决你的问题,请参考以下文章

Perl 程序高效处理目录中的 500,000 个小文件

如何循环遍历 Perl 目录中的文件? [复制]

在主目录中安装perl模块时出现问题

默认情况下,Perl 不包含 @INC 中的当前目录吗?

默认情况下,Perl 不包含 @INC 中的当前目录吗?

如何运行位于子目录中的脚本? ImportError:没有名为x的模块