2016-10-14 36 views
1

有什么方法可以事先报告Perl文件中使用的缺失模块,而不是将其作为错误报告。检查并报告缺少Perl模块

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

回答

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区块所捕获,并设置了[email protected]。然后我们可以检查它是否包含我们的模块名称,在这种情况下,我们天真地认为失败是因为该模块未安装。这项检查可能会更详细。

我们跟踪$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 ([email protected] && [email protected] =~ /$module/) { 
      warn "You need to install the $module module"; 
      $fails++; 
     } 
    } 
    exit if $fails; 
} 

# ... 

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

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

您可能希望使该消息更加冗长。如果您的用户无法理解Perl在找不到模块时提供的默认错误消息,那么可以明智地包含关于如何在此处安装东西的指南。

请注意,您列出的两个模块已包含在Perl中,用于a while(阅读:自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,但基本是一样的。

这样,你的用户就可以自动安装所有的依赖关系。

+0

感谢提及_perlnewmod_。我一直想知道CPAN如何获得人口。 – PerlDuck

+0

除了那个doc @PerlDuck还有很多。有各种工具可以启动新的发行版,还有一些指南。也许这是在CPAN上发布一些东西的好时机。开始建立一个暂停帐户。 :) – simbabque

+0

我真的不熟悉生成文件或cpanfile,开始工作的单个文件谢谢你,但如果我想检查文件夹中的所有perl文件如何可以做 – VSr

1

你的问题并不清楚“预先”的含义。要检查Perl程序的语法是正确的,直接计入模块解析,使用

perl -c <perl-program.pl> 

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

+2

如果你的意思是你的代码使用模块'use'd,那么是的,它是的。它不能做的是检查在运行时使用'require'加载的模块。 – mbethke

+1

如果'test1.pl'在同一个目录下使用'test2.pm',并且'test2.pm'有一个糟糕的'use'语句,它将只被一个expicit'perl -c test2.pm'捕获,而不是' perl -c test1.pl' –

+0

适用于perl 5.24,我非常确定它一直如此。 '$ echo'使用X;“ > x.pl; echo“package X; use Y;” > X.pm; perl -c x.pl'导致'Can not locate Y.pm in @ INC' – mbethke