【问题标题】:global level exception handling in perlperl 中的全局级异常处理
【发布时间】:2016-06-12 03:35:12
【问题描述】:

我编写了一个 perl 程序,它在内部调用了三个 perl 模块。我的主管在查看代码后要求我添加全局异常处理。我不明白他这是什么意思。他还说使用 Eval 来完成这个。我不知道如何使用 Eval 以便它捕获 enire perl 模块中的任何异常。任何人都可以通过提供链接或提供解释来帮助我吗? 提前致谢。

【问题讨论】:

  • 我想你可能得问问你的主管了!就我而言,Perl 中的全局异常处理涉及通过将子例程分配给$SIG{__DIE__} 来编写die 处理程序(如perlvar 中所述)。而且它真的只对调试有用。另一方面,eval 允许您仅在一个代码块中处理错误。我想如果你有一个执行整个程序的main() 子例程,就像在 C 中一样,那么你可以把它放在一个 eval { main(); } 块中,但我不确定我是否明白这一点。
  • 您从AmadanBorodin 那里得到了很好的建议和信息,他们的评论也表达了一个事实,即不太清楚您的情况是什么; “全局异常处理”对我来说是一个奇怪的术语。这里有几个问题:您从这些模块中调用函数的次数/频率是多少?在什么级别——深埋在潜艇内部或main::?有哪些模块?整个项目的规模和结构是什么?简而言之,我的意思是。
  • 这是一个非常小的项目,由大约 400 行代码组成。我的主管需要的是 - 我总共有 4 个程序(一个主程序和三个从主程序调用的子模块)。对于每个程序,他希望我有一个异常处理,如果出现问题,它将突出显示,便于我们调试。
  • @nithin:但这已经发生了。如果您的代码遇到致命错误,那么它会终止并显示一条消息,给出原因,以及当时正在执行的源文件和行号。你的主管显然让我和许多其他 Stack Overflow 订阅者感到困惑,因为到目前为止你根本没有答案。他们是否要求堆栈回溯?仅仅知道失败发生在代码中的哪个位置可能是不够的,因为原因最终是由于错误的参数被传递给子例程。向您的主管询问错误的示例以及他们想要的信息

标签: perl perl-module


【解决方案1】:

他希望我对每个程序进行异常处理,如果出现问题,它会被突出显示,便于我们调试。

当发生未捕获的异常时,将其打印到 STDERR。您的突出显示要求已得到满足。

异常消息已经包含了它们被抛出的行号(除非特别禁止),所以一些有助于调试的信息已经可用。

$ perl -e'sub f { die "bar" } f("foo")'
bar at -e line 1.

在您的脚本中添加use Carp::Always; 也会导致提供堆栈回溯,从而提供更多信息。

$ perl -e'use Carp::Always; sub f { die "bar" } f("foo")'
bar at -e line 1.
        main::f("foo") called at -e line 1

【讨论】:

    【解决方案2】:

    给你的问题似乎不精确。 “全球”和eval有些矛盾,因为 Borodin 在他的评论中解释。 ikegami 的回答中给出了另一种“全局”做事的方法。然而,由于提到eval ,这里是一个非常基本的使用的概要。

    您在代码块(或表达式,但这不是您想要的)上使用eval。如果die 被抛出该块内的任何地方,eval 就会捕捉到,从某种意义上说,您将控制权取回,程序不会直接死掉。变量$@ 被错误消息填充。然后您可以询问发生了什么,打印出诊断信息,并可能从错误中恢复。

    eval {  run_some_code(@args) };
    if ($@) {
        carp "Error in `run_some_code()`: $@ --";
        # Do further investigation, print, recover ...
    }
    

    您可以在上面的eval 块中包含任何代码,它不必是单个函数调用。请注意,eval 本身返回的值传达了所发生的情况($@ 除外)。

    至于问题陈述中的“全局”,想到的一件事是您在main:: 的级别上使用eval - 将任何自己从模块调用函数的子程序包装在其中。

    关于异常的一个关键点是它们会“冒泡”。当一个die(Perl 的唯一例外)被抛出一个子并且调用者没有eval 它时,它会沿着调用链上升......最终出现在main::,如果它没有被捕获( eval-ed)那里然后程序死了。因此,您可以在main:: 中的顶级调用eval 并了解下面的任何地方是否出错。

    eval { top_level_call(); };
    if ($@) {
        warn "Error from somewhere in `top_level_call(): $@";
    }
    
    # Functions
    sub top_level_call {
        # doing some work ...
        another_sub();
        # doing more ...
    }
    sub another_sub {
        # do work, no eval checks
    }
    

    如果在another_sub() 中发生触发die 的错误,则其处理将立即停止并将控制权返回给调用者top_level_call()。由于该子不检查(没有eval 那里)它的执行也停止在那个点,并且控制返回给它的调用者(在这个例子中是main:: 本身)。所以它最终会到达main::,而eval-ing 会让你知道错误,你的程序不会直接退出。

    也许这就是使用eval 进行“全局”异常处理的意思。

    如果这是你需要做的,你可以沿着这些思路做更多的事情。对于初学者,请参阅eval。 通过澄清更新您的问题,以便您在此处获得更多讨论。

    实际上,我会说你让自己对eval 的使用以及一些“全局”错误报告有所了解,然后按照@987654324 的建议向你的主管寻求说明和/或示例@。

    【讨论】:

      猜你喜欢
      • 2016-11-03
      • 2019-07-18
      • 2017-02-24
      • 2011-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-21
      • 2011-09-29
      相关资源
      最近更新 更多