有没有办法事先报告Perl文件中使用的丢失模块,而不是作为错误.
我有一些像use Digest::MD5,use File::DosGlob模块在我的Perl程序.每当用户运行脚本时,如果系统中没有安装特定模块,则会出现错误.他们无法理解由...给出的默认错误消息@INC.所以我想清楚告诉他们需要安装这些模块来运行脚本.
您可以使用Devel :: Modlist,它将列出您的程序所需的所有模块.
perl -d:Modlist test.pl
Run Code Online (Sandbox Code Playgroud)
还有另一个模块Module :: ScanDeps,它附带了一个实用程序scandeps.pl,您可以在脚本上使用它:
scandeps.pl test.pl
Run Code Online (Sandbox Code Playgroud)
请注意,检查Perl代码的完整性perl -c是危险的,因此请谨慎使用.
你可以通过建立自己的验证一个BEGIN块.那些是在编译时运行的,就像use是.请记住,use Foo基本上没有其他内容如下:
BEGIN {
require Foo;
Foo->import;
}
Run Code Online (Sandbox Code Playgroud)
以下代码将use使用单个替换所有语句BEGIN并将它们放在一个中eval.这基本上就像一个try/catch机制.
我们需要字符串eval(这里被认为是邪恶的),因为如果参数是一个单词,require只能从带有冒号的包名转换::为路径.但是因为我们有名字,所以它是一个字符串,所以我们需要将它放入一个根据文档.$moduleevalrequire
如果该字符串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;
}
# ...
Run Code Online (Sandbox Code Playgroud)
上面我包括ASDF,我没有,所以在运行时它会说
您需要在/home/code/scratch.pl第1335行安装ASDF模块.
您可能希望使该消息更加冗长.如果您的用户无法理解Perl在找不到模块时提供的默认错误消息,那么在其中包含有关如何安装内容的指南可能是明智之举.
请注意,您列出的两个模块都已包含在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
Run Code Online (Sandbox Code Playgroud)
更好的方法是将程序作为可安装的发行版发布,并包含Makefile或cpanfile或列出依赖项的类似内容.perlnewmod中有一个关于如何启动新模块的指南.您不希望显然上传到CPAN,但基本内容是相同的.
有了这个,您的用户将自动安装所有依赖项.