如果在它使用的模块中引发异常,我如何防止我的 perl 脚本终止?

Posted

技术标签:

【中文标题】如果在它使用的模块中引发异常,我如何防止我的 perl 脚本终止?【英文标题】:How can I prevent my perl script from terminating if an exception is thrown in a module it uses? 【发布时间】:2012-01-10 18:53:38 【问题描述】:

我有一个 perl 脚本,使用标准的 Net::HTTP 代码和 perl 5.8.8。 我遇到了一个错误情况,当我调用时服务器返回 0 字节的数据:

$_http_connection->read_response_headers;

不幸的是,我的 perl 脚本 dies,因为 Net::HTTP::Methods 模块在第 306 行有一个“死”:

Server closed connection without sending any data back at
/usr/lib/perl5/vendor_perl/5.8.8/Net/HTTP/Methods.pm line 306

当然,第 305-307 行是:

unless (defined $status) 
die "Server closed connection without sending any data back";

我怎样才能让我的脚本从这种情况“正常恢复”,检测到die,然后进入我自己的错误处理代码,而不是dieing 本身?

我确信这是一个常见的情况,可能很简单,但我以前没有遇到过。

【问题讨论】:

【参考方案1】:

使用eval 捕捉异常can occasionally be problematic,尤其是5.14 之前的版本。你可以使用Try::Tiny。

【讨论】:

我无法在这个系统上安装模块,这是我试图解决的一个罕见问题,所以“eval”现在必须做,但我会保留 Try::Tiny考虑到其他项目。谢谢。 如果您可以在该系统上放置脚本,您也可以在该系统上使用Try::Tiny,即使您只是复制 &将模块源代码粘贴到您的脚本中。 技术上肯定,但不值得付出努力,因为这个小内部脚本将解决大量问题。即使它由于 Net::HTTP 问题而死,也只是我们是否在自己死之前记录问题。如果我们错过了它,那也不是世界末日。 :)【参考方案2】:

您可以使用eval 来捕获die() 异常。使用$@ 检查抛出的值:

eval 
    die "foo";
;
print "the block died with $@" if $@;

详情请见http://perldoc.perl.org/functions/eval.html

【讨论】:

在 Perl 5.14 之前,eval 最好写成 my $success = eval code_that_may_die(); 1; ; if (!$success) print "Error: $@" 这是由于一个相当罕见的问题,即在退出 eval 块时,$@ 的值可能会被清除。从 5.14 开始,任何一种方式都可以使用。【参考方案3】:

die 自定义为其他含义很简单:

sub custom_exception_handler  ...  # Define custom logic

local $SIG__DIE__ = \&custom_exception_handler;  # Won't die now
# Calls custom_exception_handler instead

eval 相比,这种方法的最大优势在于它不需要调用另一个 perl 解释器来执行有问题的代码。

当然,自定义异常处理程序应该足以应付手头的任务。

【讨论】:

以上是关于如果在它使用的模块中引发异常,我如何防止我的 perl 脚本终止?的主要内容,如果未能解决你的问题,请参考以下文章

如果设置了 GD 标志,读取调试寄存器是不是会引发异常?

如何在引发时将变量传递给异常并在异常时检索它?

防止来自 3rd 方组件的异常使整个应用程序崩溃

如何使用 Mockery 在模拟方法的第 N 次调用中引发异常

如何跳过循环中的迭代?

如何跳过循环中的迭代?