【问题标题】:What is the best way to handle exceptions in Perl?在 Perl 中处理异常的最佳方法是什么?
【发布时间】:2011-04-29 16:59:30
【问题描述】:

我注意到 Exception.pm 和 Error.pm 在 Perl 社区中似乎没有被广泛使用。这是因为eval 用于异常处理的占用空间很大吗?

此外,Perl 程序似乎对一般异常处理有更宽松的政策。这有什么令人信服的理由吗?

无论如何,在 Perl 中处理异常的最佳方法是什么?

【问题讨论】:

标签: perl exception-handling error-handling eval


【解决方案1】:

Perl 社区的共识似乎是Try::Tiny 是进行异常处理的首选方式。您所指的“宽松政策”可能是由于以下因素的结合:

  • Perl 不是完全面向对象的语言。 (例如,与 Java 相比,其中 你无法避免处理异常。)
  • 许多 Perl 开发人员的背景。 (像 C1 和 shell 这样的语言没有 异常机制。)
  • 人们倾向于使用 Perl 完成的任务类型。 (用于文本处理的小脚本和 在不需要异常处理的情况下生成报告。)
  • Perl 没有(好的)内置异常机制。

注意最后一项意味着你会看到很多这样的代码:

eval { something() };
if ($@) {
    warn "Oh no! [$@]\n";
}

这是异常处理,即使它不使用 try/catch 语法。但是,它很脆弱,并且会在大多数人没有想到的许多微妙的边缘情况下打破。 Try::Tiny 和 CPAN 上的其他异常处理模块是为了更容易正确处理而编写的。

1。 C 确实有setjmp()longjmp(),可用于非常粗略的异常处理形式。

【讨论】:

  • 并且只是为了澄清原始发布者可能会或可能不会遭受的常见误解:eval BLOCKnot eval STRING 并且不会在运行时编译代码.它只是一种异常处理方法——try 有一个有趣的名字和略带滑稽的语义。
  • 如果我们认为setjmp+longjmp 是 C 中的一种异常处理机制(无论多么粗糙),那么 shell 也有一个:trap+kill(尽管它看起来更粗糙)。
  • 供您参考,现在 perl 中有一个完整的 try-catch 实现,模块 Nice::Try
【解决方案2】:

千万不要按原样测试$@,因为它是一个全局变量,所以即使是测试本身也可以改变它。

通用评估模板:

my $result;

eval {
    $result= something();
    # ...
    1;  # ok
} or do {
    my $eval_error= $@ || "error";
    # ...
    die $eval_error;
};  # needs a semicolon

在实践中,这是最轻松的方式。它仍然为有趣的 $@ 行为留下了很小的空间,但没有什么让我真正关心的足够多。

【讨论】:

    【解决方案3】:

    正如已经提到的,您可以使用传统方式与eval,但如果您想使用更复杂的异常捕获,包括异常对象,那么我建议使用 try-catch-finally 块。 有不少 perl 模块提供它,例如 Nice::TrySyntax::Keyword::Try,但 Syntax::Keyword::Try 不提供异常变量赋值或异常类捕获之类的

      try
      {
        # something
      }
      catch( Exception $e )
      {
        # catch this in $e
      }
    

    完全披露:我是Nice::Try的开发者

    【讨论】:

    • Nice::Try 非常棒,它拥有我在 Perl 中处理异常时一直想要的一切。
    猜你喜欢
    • 1970-01-01
    • 2021-02-22
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多