3

我想检测用户何时缺少必需的模块并打印一条友好的错误消息,说明他们需要安装什么。

到目前为止,我尝试将其放在脚本的开头:

eval {
    use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
};
if ($@) {
    die "Error: IO::Uncompress::Gunzip not installed: $@";
}

但是 Perl 似乎死在“使用”行而不是“死”行上,并且从不打印我的错误消息。

4

3 回答 3

10
use IO::Uncompress::Gunzip qw( gunzip $GunzipError );

简称

BEGIN {
   require IO::Uncompress::Gunzip;
   import IO::Uncompress::Gunzip qw( gunzip $GunzipError );
}

BEGIN块在编译后立即进行评估。这意味着您的代码可以:

  1. 编译阶段:
    1. 编译eval语句。
      1. 编译BEGIN块。
        1. 编译require IO::Uncompress::Gunzip;
        2. 编译import IO::Uncompress::Gunzip qw( gunzip $GunzipError );
      2. 评估BEGIN块。
        1. 评估require IO::Uncompress::Gunzip;
        2. 评估import IO::Uncompress::Gunzip qw( gunzip $GunzipError );
    2. 编译if语句。
  2. 运行阶段:
    1. 评估(空) eval语句。
    2. 评价if陈述。

如果步骤 1.1.2.1 中发生异常,则eval步骤 2.1 中的运行不会捕获它!


解决方案:

你从等同于的东西开始

BEGIN {
   require IO::Uncompress::Gunzip;
   import IO::Uncompress::Gunzip qw( gunzip $GunzipError );
}

这是require您想要捕获的错误,因此只需在eval周围添加一个require

BEGIN {
   eval { require IO::Uncompress::Gunzip }
      or die "Error: IO::Uncompress::Gunzip not installed: $@";

   import IO::Uncompress::Gunzip qw( gunzip $GunzipError );
}

您还可以通过使用而不是延迟use编译(并因此评估):eval EXPReval BLOCK

BEGIN {
   eval 'use IO::Uncompress::Gunzip qw( gunzip $GunzipError ); 1'
      or die "Error: IO::Uncompress::Gunzip not installed: $@";
}

(我希望有一种很好的方法来确定是否安装了模块。即使第一个解决方案也会捕获其他错误,第二个甚至更多。)

于 2012-06-13T18:39:45.783 回答
5

这里发生的是模块在编译时被d,不管它在块use内的事实。eval

这也是为什么naab 建议eval BLOCK一种形式到另一种形式的转变也有效的原因eval EXPR;表达式在运行时进行评估。更改userequire将尝试在运行时加载模块:

eval {
    require IO::Uncompress::Gunzip;
    IO::Uncompress::Gunzip->import( qw/gunzip $GunzipError/ ) ;
};
if ($@) {
    die "Error: IO::Uncompress::Gunzip not installed: $@";
}

输出

错误:IO::Uncompress::Gunzip not installed: Can't locate IO/Uncompress/Gunzip.pm in @INC (@INC contains: C:/Perl/site/lib C:/Perl/lib .) at - line 2.

于 2012-06-13T18:34:01.933 回答
0

查看 Class::Load 的 try_load_class ( CPAN )

use Class::Load;
die "Error: IO::Uncompress::Gunzip not installed" if 
    (! try_load_class (IO::Uncompress::Gunzip));

但据我所知,您不能使用 Class::Load 导入 qw(gunzip $GunzipError)。

于 2012-12-17T21:29:06.653 回答