【问题标题】:How can my Perl script find its module in the same directory?我的 Perl 脚本如何在同一目录中找到它的模块?
【发布时间】:2010-10-18 05:37:33
【问题描述】:

我最近编写了一个新的 Perl 脚本来根据进程名称/用户名终止进程,并使用类对其进行扩展,以便我可以在其他程序中重用进程代码。我目前的布局是 -

/home/mutew/src/prod/pskill       <-- Perl script
/home/mutew/src/prod/Process.pm   <-- Package to handle process descriptions

我在 $PATH 变量中添加了 ~/src/prod 以从任何地方访问脚本。从其驻留目录以外的任何目录运行脚本会导致“无法在 @INC 中找到 Process.pm”(这是可以理解的,因为除了 /usr 中的共享目录之外,@INC 仅包括当前目录 - '.')。我一直在使用的一种解决方法是使用 lib 指令 -

use lib '/home/mutew/src/prod';

但这是一个主要的可移植性问题。任何解决方案也可以让我将脚本导出到其他系统而无需更改?


编辑

  1. 我选择“depesz”作为正确答案是因为它的简单性和核心模块的使用。
  2. brian d foy 的回答虽然提出了其他方法来完成相同的任务 (TMTOWTDI),但他在 perlfaq8 中的贡献使这个问题变得绝对多余。

【问题讨论】:

  • 也许这只是我的安装,但如果两个文件都在同一个目录中,我只需“使用 FILENAME.pm”。然后“我的 $newVar = PACKAGENAME->new();”适用于任何对象编程。
  • 哇,这在 perl 中应该比这容易得多!让简单的事情变得简单等等。

标签: perl module directory


【解决方案1】:

我很好奇为什么简单的解决方案

use File::Basename;
use lib dirname (__FILE__);
use SomeModuleLocatedInTheSameDirectoryAsThisPerlScriptOrModule;

没有出现。如果文件不是主要的可执行 perl 脚本,而只是一个不可执行的 Perl 模块,则 FindBin 模块似乎存在一些问题。至少我是这样解释documentation 中的评论的。并没有真正测试它。

要获得相对于该 Perl 文件位置的任何其他路径,请执行以下操作

use File::Basename;
use lib dirname (__FILE__) . "/MyModules";

【讨论】:

  • 我非常喜欢这种方法——我只需要使用use Cwd qw(abs_path); use lib dirname (abs_path(__FILE__)); 来使脚本可以通过符号链接调用。干杯!
  • 这是通过谷歌搜索几分钟对我有用的唯一答案。并且足够简单,足够清晰,对新手友好。
  • 这不适用于命名空间模块,例如如果在somedir/Foo/Bar 下,您在Baz.pm 中有Foo::Bar::Baz,并且您想从同一目录中的Qux.pm 中的Foo::Bar::Qux 导入它。
  • 谢谢,大卫,值得考虑的有趣点。我只想补充一点,如果您使用命名空间,那么最好的做法不是也总是使用它们的全限定名称导入模块吗?否则,根据使用的 lib 搜索路径,您最终可能会导入错误的模块。
【解决方案2】:

我发现最简单的方法是使用 FindBin 模块。像这样:

use FindBin;
use lib $FindBin::Bin;

一般来说,我更喜欢以这样一种方式提供我的脚本,即程序在whatever/bin中,而库在whatever/lib中

在这些情况下,我使用稍微复杂一点的方法:

use Cwd qw(abs_path);
use FindBin;
use lib abs_path("$FindBin::Bin/../lib");

abs_path 调用是为了让@INC 包含whatever/lib,而不是whatever/bin/../lib——这只是一个微小的改变,但是让阅读错误信息更容易。

【讨论】:

  • 不要忘记 abs_path 在污染模式下返回污染结果。您必须使用 use lib (abs_path("$FindBin::Bin/../lib")=~m{^(/.*)})[0]; 或只使用 use lib "$FindBin::Bin/../lib"; 因为没有理由规范路径。
  • 这个解决方案有效,但我选择了第二个解决方案(如下),因为 FindBin 必须与 CPAN 一起安装,而且我更喜欢 File::Basename 作为核心模块的不受阻碍的方面,当运行时多台机器。
【解决方案3】:

来自perlfaq8,回复"How do I add a directory to my include path (@INC) at runtime?"。围绕这个问题还有其他几个问题的答案。


如何在运行时将目录添加到我的包含路径 (@INC)?

以下是修改包含路径的建议方法,包括环境变量、运行时开关和代码内语句:

PERLLIB 环境变量

$ export PERLLIB=/path/to/my/dir
$ perl program.pl

PERL5LIB 环境变量

$ export PERL5LIB=/path/to/my/dir
$ perl program.pl

perl -Idir 命令行标志

$ perl -I/path/to/my/dir program.pl

使用库编译指示:

use lib "$ENV{HOME}/myown_perllib";

最后一个特别有用,因为它了解与机器相关的架构。 lib.pm 实用模块首先包含在 Perl 的 5.002 版本中。

【讨论】:

  • 我在同一天晚些时候阅读了 perlfaq8,并在您投稿的文章中找到了我需要的答案。我想知道为什么你确实包含了第二种方法(使用 Cwd),因为@INC 已经有一个当前目录的条目 - '.'
【解决方案4】:

除了已经说明的解决方案:

  1. 使用 FindBin / lib
  2. Perl 常见问题解答 8 How do I add a directory to my include path (@INC) at runtime?

我在之前开发/测试模块时使用的“最简单的方法”(™) 部署它(在 /usr/local/lib/site_perl/ 或 @INC 的其他地方)是 在加载模块之前修改@INC如下:

#!/usr/bin/perl
use strict;
use warnings;
# Modify @INC prior to module loading.
BEGIN { unshift @INC, '.'; }
use YourModuleInCWD;

(Add current working directory to @INC? - PerlMonks)

【讨论】:

    【解决方案5】:

    您可以使用-I 标志让perl 查看任何目录。这里,-I 代表@INC,它是 perl 查找模块的路径数组。使用-I 将给定的路径添加到@INC 数组以执行此操作。

    例如:

    perl -I lib bin/script.pl
    

    其中 lib 包含我要使用的模块。

    我知道这适用于 perl 5。我不确定其他版本。

    【讨论】:

    • 这是最好的答案。例如: #! /usr/bin/env perl -I ./ 简单的解决方案总是比包含另一个晦涩的 CPAN 模块更好。
    【解决方案6】:

    看看Par::Packer。它创建一个包含所有脚本依赖项的可执行文件。它使分发变得容易。您还可以为您的用户提供可以安装在他们系统上的模块版本。请参阅Module::Starter,以轻松构建制作标准 CPAN 样式分发所需的所有文件。

    【讨论】:

      【解决方案7】:

      要将相对链接转换为绝对链接并添加到@INC,我通常使用ex::lib。当然,仅当您计划在计划运行脚本的所有机器上保持脚本和模块的相对位置相同时,这才有用。

      【讨论】:

        【解决方案8】:

        保持简单。无需导入任何库;只需找出您当前的工作目录:

        use lib "$ENV{PWD}/relativ_path_own_perllib";
        

        对于类似的问题,您可以读取环境变量,该变量提供您的位置、主目录、操作系统内容等信息,只需在 shell 终端中使用一行编程代码,例如:

        perl -e 'map { print; print " : ". $ENV{$_}." \n\r"; } sort keys %ENV '
        

        有些库不需要绑定;只需使用%ENV-Hash

        【讨论】:

        • $ENV{PWD} 没有解决问题 - 相反。它返回用户的工作目录,而不是脚本的位置。
        【解决方案9】:

        FindBin::libs 会发现你的所有库都放置在相对于脚本运行路径的合理位置。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-06-09
          • 2010-09-26
          • 1970-01-01
          • 1970-01-01
          • 2022-07-21
          • 1970-01-01
          • 2023-03-13
          • 1970-01-01
          相关资源
          最近更新 更多