Perl - eval没有捕获“use”语句

时间:2012-06-13 18:15:40

标签: perl

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

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

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

但Perl似乎死于"使用"而不是" die"行,永远不会打印我的错误信息。

3 个答案:

答案 0 :(得分: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声明。
  3. 如果在步骤1.1.2.1中发生异常,则步骤2.1中的eval运行将无法捕获它!


    解决方案:

    你从等同于

    的东西开始
    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 EXPR来延迟eval BLOCK编译(并因此评估):

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

    (我希望有一种很好的方法可以找出是否安装了一个模块。即使第一个解决方案会捕获其他错误,第二个解决方案会更多。)

答案 1 :(得分:5)

这里发生的是模块在编译时是use d,无论它是否在eval块内。

这也是naab's suggestioneval BLOCK形式更改为eval EXPR形式的原因;表达式在运行时进行评估。 将use更改为require将尝试在运行时加载模块:

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

<强>输出

  

错误:IO :: Uncompress :: Gunzip未安装:无法在@INC中找到IO / Uncompress / Gunzip.pm(@INC包含:C:/ Perl / site / lib C:/ Perl / lib。)在线2。

答案 2 :(得分: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)。