如何正确使用www.example.com提供的perl中的try catcherror.pm?

sirbozc5  于 2022-11-15  发布在  Perl
关注(0)|答案(7)|浏览(162)

我发现有一个模块Error提供了类似java的try和catch功能,但是我对如何打印返回的异常感到困惑。
我想了解如何执行以下操作

try {
    // do something that will fail!

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

如何使用堆栈跟踪获取错误的打印结果?

rn0zuynd

rn0zuynd1#

您最好使用Try::Tiny,它将帮助您避免使用旧的perl的许多陷阱。

use Try::Tiny;

try {
        die "foo";
} catch {
        warn "caught error: $_";
};
jpfvwuh4

jpfvwuh42#

上次我检查的时候,Error已经过时了。但是下面是没有这个模块的情况:

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

基本上,使用eval代替try,使用die代替throw,并在$@中查找异常。eval块末尾的true值是一个习惯用法的一部分,用于防止$@在Perl 5.14之前被再次使用之前被无意中更改,有关详细信息,请参见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

kgsdhlau

kgsdhlau3#

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

zy1mlcev

zy1mlcev4#

原生try/catch/finally

Perl now has native support for try / catch / finally。您可以像这样使用它。从Perl v5.36, It's currently experimental.开始

use experimental "try";
try { die 42 }
catch ($err) {
  print "got $err"
}
o2g1uqev

o2g1uqev5#

不幸的是,TryCatchDevel::Declare的新版本0.006020中被破坏了,而且似乎没有修复它的意图。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被破坏时,我开发了这个模块。

biswetbf

biswetbf6#

IMHO Syntax::Keyword::Try在大多数情况下是比Try::Tiny更好的选择。
Try::Tiny比eval或Syntax::Keyword::Try慢一个数量级。这是否是个问题取决于您的应用程序。对于许多应用程序来说,这并不重要。
此外,如果您是来自另一种语言的访问者,Try::Tiny有一些语法怪癖,这使得它不太像您习惯的try/catch。

uurity8g

uurity8g7#

正如前面所说的,旧的Error模块已经过时了,但是它在很长一段时间后仍然为我工作。自从我上次检查它是否仍然工作以来已经有一段时间了。我尝试了一些“更好的”替代品,发现它们都没有,所以我仍然使用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上的stacktrace方法,以获得Error类本身。我从来没有发现有必要让不在调试器下运行的应用程序打印完整的堆栈跟踪,所以我的集合中没有任何这样的例子可以粘贴。
我希望这能帮上忙。有时候你只需要等待恐龙的出现。

相关问题