【发布时间】:2011-04-29 16:59:30
【问题描述】:
我注意到 Exception.pm 和 Error.pm 在 Perl 社区中似乎没有被广泛使用。这是因为eval 用于异常处理的占用空间很大吗?
此外,Perl 程序似乎对一般异常处理有更宽松的政策。这有什么令人信服的理由吗?
无论如何,在 Perl 中处理异常的最佳方法是什么?
【问题讨论】:
标签: perl exception-handling error-handling eval
我注意到 Exception.pm 和 Error.pm 在 Perl 社区中似乎没有被广泛使用。这是因为eval 用于异常处理的占用空间很大吗?
此外,Perl 程序似乎对一般异常处理有更宽松的政策。这有什么令人信服的理由吗?
无论如何,在 Perl 中处理异常的最佳方法是什么?
【问题讨论】:
标签: perl exception-handling error-handling eval
Perl 社区的共识似乎是Try::Tiny 是进行异常处理的首选方式。您所指的“宽松政策”可能是由于以下因素的结合:
注意最后一项意味着你会看到很多这样的代码:
eval { something() };
if ($@) {
warn "Oh no! [$@]\n";
}
这是异常处理,即使它不使用 try/catch 语法。但是,它很脆弱,并且会在大多数人没有想到的许多微妙的边缘情况下打破。 Try::Tiny 和 CPAN 上的其他异常处理模块是为了更容易正确处理而编写的。
1。 C 确实有setjmp() 和longjmp(),可用于非常粗略的异常处理形式。
【讨论】:
eval BLOCK 是 not eval STRING 并且不会在运行时编译代码.它只是一种异常处理方法——try 有一个有趣的名字和略带滑稽的语义。
setjmp+longjmp 是 C 中的一种异常处理机制(无论多么粗糙),那么 shell 也有一个:trap+kill(尽管它看起来更粗糙)。
千万不要按原样测试$@,因为它是一个全局变量,所以即使是测试本身也可以改变它。
通用评估模板:
my $result;
eval {
$result= something();
# ...
1; # ok
} or do {
my $eval_error= $@ || "error";
# ...
die $eval_error;
}; # needs a semicolon
在实践中,这是最轻松的方式。它仍然为有趣的 $@ 行为留下了很小的空间,但没有什么让我真正关心的足够多。
【讨论】:
正如已经提到的,您可以使用传统方式与eval,但如果您想使用更复杂的异常捕获,包括异常对象,那么我建议使用 try-catch-finally 块。 有不少 perl 模块提供它,例如 Nice::Try 和 Syntax::Keyword::Try,但 Syntax::Keyword::Try 不提供异常变量赋值或异常类捕获之类的
try
{
# something
}
catch( Exception $e )
{
# catch this in $e
}
完全披露:我是Nice::Try的开发者
【讨论】: