36

我发现有一个模块Error提供了 java 中的 try 和 catch 功能。但是我对如何打印返回的异常感到困惑。

我想了解如何执行以下操作

try {
    // do something that will fail!

} catch (Error e) {
    // Print out the exception that occurred
    System.out.println(e.getMessage());
}

如何使用堆栈跟踪打印错误?

4

6 回答 6

56

您可能最好使用Try::Tiny,这将帮助您避免一些perls的陷阱。

use Try::Tiny;

try {
        die "foo";
} catch {
        warn "caught error: $_";
};
于 2012-04-27T00:53:28.940 回答
50

最后我检查,错误已被弃用。但是,如果没有该模块,您将如何做到这一点:

eval {
    die "Oops!";
    1;
} or do {
    my $e = $@;
    print("Something went wrong: $e\n");
};

基本上,使用eval代替trydie代替throw,并在$@. eval 块末尾的真值是一个习惯用法的一部分,用于防止$@在 5.14 之前的 Perl 版本中再次使用它之前无意更改,有关详细信息,请参阅P::C::P::ErrorHandling::RequireCheckingReturnValueOfEval。例如,这段代码就存在这个缺陷。

# BAD, DO NOT USE WITH PERLS OLDER THAN 5.14
eval {
    die "Oops!";
};
if (my $e = $@) {
    print("Something went wrong: $e\n");
}
# BAD, DO NOT USE WITH PERLS OLDER THAN 5.14

但请注意,许多 Perl 操作在失败时不会引发异常;他们只是返回一个错误代码。可以通过autodie为内置和标准模块更改此行为。如果您正在使用autodie,那么执行 try/catch 的标准方法是这样的(直接来自 autodie perldoc):

use feature qw(switch);

eval {
   use autodie;

   open(my $fh, '<', $some_file);

   my @records = <$fh>;

   # Do things with @records...

   close($fh);

};

given ($@) {
   when (undef)   { say "No error";                    }
   when ('open')  { say "Error from open";             }
   when (':io')   { say "Non-open, IO error.";         }
   when (':all')  { say "All other autodie errors."    }
   default        { say "Not an autodie error at all." }
}

要获取堆栈跟踪,请查看Carp

于 2012-04-26T23:57:14.247 回答
8

如果您想要比 Try::Tiny 更强大的东西,您可能想尝试查看 CPAN 中的TryCatch模块。

于 2013-06-06T18:58:03.480 回答
1

不幸的是, Devel::Declare的新版本 0.006020 破坏了TryCatch,似乎没有修复它的打算。perl 核心开发团队也抱怨 TryCatch 依靠一些时髦的东西来使其工作。

取而代之的是一个名为Nice::Try的新实现,它是一个完美的替代品。

最后一个大括号不需要像 Try::Tiny 这样的分号。

您还可以进行异常变量赋值,例如

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

它也可以使用类异常,例如

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

它还支持finally. 它的功能集使其非常独特。

完全披露:当 TryCatch 被破坏时,我开发了这个模块。

于 2020-06-02T04:15:55.347 回答
0

恕我直言Syntax::Keyword::Try,是比Try::Tiny大多数情况更好的选择。

Try::Tiny比 eval 或 慢一个数量级Syntax::Keyword::Try。这是否存在问题取决于您的应用程序。对于许多应用程序来说,它并不重要。

此外,如果您是来自另一种语言的访问者,Try::Tiny则存在语法怪癖,这使其与您习惯的 try/catch 不太一样。

于 2021-07-02T11:59:01.913 回答
0

如前所述,旧的错误模块已被弃用,但它在很长一段时间后仍然对我有用。自从我上次检查它是否仍然工作以来已经有一段时间了。我尝试了一些“更好”的替代品,发现它们都缺少,所以我仍然使用 Error。

这是一些代码的示例,该示例非常简单,并打印了捕获的错误。这是来自我编写的一个应用程序,它使用 Storable 将序列化的 perl 对象存储和检索到 MLDBM 后端文件。

use Error(':try');
...

     try {
        $obj = retrieve( $objfile );
      } catch Error::Simple with {
        my $E = shift;
        warn "Caught error $E";
      };

这将返回一条消息,例如:

Caught error Not a HASH reference at ./json2text.pl line 12.

如果您想要完整的堆栈跟踪,您可以在调试器下运行代码,或者您可以阅读 perldoc 上有关 Error 类本身的堆栈跟踪方法。我从来没有发现有必要让应用程序不在调试器下运行来打印完整的堆栈跟踪,所以我的集合中没有任何示例可以从中粘贴示例。

我希望这有帮助。有时你只需要等待恐龙出现。

于 2021-11-10T21:18:01.597 回答