检查并报告缺少Perl模块

时间:2016-10-14 04:20:06

标签: perl perl-module

有没有办法事先报告Perl文件中使用的丢失模块,而不是出错。

我的Perl程序中有use Digest::MD5use File::DosGlob个模块。每当用户运行脚本时,如果系统中没有安装特定模块,则会出现错误。他们无法理解@INC给出的默认错误消息。所以我想清楚告诉他们需要安装这些模块来运行脚本。

3 个答案:

答案 0 :(得分:5)

您可以使用Devel::Modlist,它会列出您的程序所需的所有模块。

perl -d:Modlist test.pl

还有另一个模块Module::ScanDeps,它带有一个实用程序scandeps.pl,您可以在脚本上使用它:

scandeps.pl test.pl

请注意sanity checking your Perl code using perl -c is dangerous,因此请谨慎使用。

答案 1 :(得分:5)

您可以使用a BEGIN block建立自己的验证。这些是在编译时运行的,就像use一样。请注意,use Foo基本上没有其他内容:

BEGIN {
    require Foo;
    Foo->import;
}

以下代码会将所有use语句替换为一个BEGIN,并将其置于eval内。这基本上就像try/catch机制。

我们需要字符串eval(这里被认为是邪恶的),因为require仅从冒号::的包名转换为路径(如果参数为a bareword)。但由于我们在$module中有名称,因此它是一个字符串,因此我们需要根据require's docs将其放入eval

如果该字符串eval失败,我们die。由外eval块和$@捕获的内容已设置。然后我们可以检查它是否包含我们的模块名称,在这种情况下我们天真地假设失败是因为没有安装该模块。这项检查可能会更精细。

我们会跟踪$fails中的任何失败,如果有失败,我们会停止。

#!/usr/bin/perl
use strict;
use warnings;

# all our use statements go here
BEGIN {
    my $fails;
    foreach my $module ( qw/Digest::MD5 File::DosGlob ASDF/ ) {
        eval {
            eval "require $module" or die; # because $module is not a bareword
            $module->import;
        };
        if ($@ && $@ =~ /$module/) {
            warn "You need to install the $module module";
            $fails++;
        }
    }
    exit if $fails;
}

# ...

上面我包括ASDF,我没有,所以在运行时会说

  

您需要在/home/code/scratch.pl第1335行安装ASDF模块。

您可能希望使该消息更加冗长。如果您的用户无法理解Perl在无法找到模块时提供的默认错误消息,那么在其中包含有关如何安装内容的指南可能是明智之举。

请注意,您列出的两个模块都包含在a while的Perl中(读取:自2002年3月起)。那你为什么要为这些模块做这个呢?

$ corelist Digest::MD5

Data for 2014-09-14
Digest::MD5 was first released with perl v5.7.3

$ corelist File::DosGlob

Data for 2014-09-14
File::DosGlob was first released with perl 5.00405

更好的方法是将程序作为可安装的发行版发布,并包含Makefile或cpanfile或列出依赖项的类似内容。 perlnewmod中有关于如何启动新模块的指南。您显然不想上传到CPAN,但基本内容是相同的。

有了这个,您的用户将自动安装所有依赖项。

答案 2 :(得分:1)

你的问题并不清楚“事先”是什么意思。要检查Perl程序的语法是否正确并且直接包含的模块是否可解析,请使用

perl -c <perl-program.pl>

这将检查文件的语法,并确保您的代码存在任何模块use。但是,它不会传递检查整个依赖关系树,只会检查perl-program.pl中提到的那些。