Python异常处理 - 返回行,继续

时间:2016-06-28 04:12:44

标签: python exception continue keyboardinterrupt

我做了很多Project Euler编码问题,Python是我的首选语言。许多程序通常需要永远完成,所以我正在努力实现一些有助于提供有关程序状态的诊断信息的内容:当KeyboardInterrupt发生时,我希望能够打印程序运行了多长时间以及一些帮助我弄清楚可能需要多长时间的信息。

这个问题是 - 当KeyboardInterrupt正在为我退出程序时抓住Ctrl-C ...我认为它与这个结构有很大关系代码,或希望在Python中的东西我还没有找到。

我希望我的代码在KeyboardInterrupt被捕后立即在同一行恢复。

以下是此代码的示例:

     try:
         ...
         ...
         ... #I interrupt code here and hopefully keep going!
         ...
         ...
     except KeyboardInterrupt:
         ...
     finally:
         ...

我希望有人理解这样做的目的,并且可以帮助我找到一种方法来做到这一点,或者解决这种从运行代码中调用中断的丑陋方式。

2 个答案:

答案 0 :(得分:3)

一般情况下,在try块中触发异常后,您永远不会将执行返回到特定代码段,因为异常可能发生在某些其他状态受到其他线程中其他副作用影响的深处。虽然你的程序可能不是这种情况,但鉴于在Python中没有通用的解决方案,你想要做的事情基本上不可能使用异常处理。

然而,SIGINT信号的默认处理程序是抛出KeyboardInterrupt异常 - 如果你可以劫持它做其他事情,你几乎可以实现这一点。这是一个简单的程序:

import signal
import pdb

def signal_handler(signal, frame):
    pdb.set_trace()

signal.signal(signal.SIGINT, signal_handler)

count = 0
while True:
    count += 1

SIGINT处理程序现在只是一个在当前帧调用调试器的函数,每当按下Ctrl-C时,调试器就会在代码所在的帧内的确切位置触发。 。你当然可以简单地上去检查这些值:

$ python /tmp/script.py 
^C--Return--
> /tmp/script.py(5)signal_handler()->None
-> pdb.set_trace()
(Pdb) u
> /tmp/script.py(10)<module>()
-> while True:
(Pdb) pp count
13321869
(Pdb) c
^C--Return--
> /tmp/script.py(5)signal_handler()->None
-> pdb.set_trace()
(Pdb) quit
Traceback (most recent call last):
...
    if self.quitting: raise BdbQuit
bdb.BdbQuit

因此调试器在ctrl-c完成后被触发,然后我将u p步骤到运行循环的帧(在你的情况下是你的代码),然后c继续执行,再次杀死它并触发了一个错误的退出(通过输入quit)来终止该程序。如果你加入这个,你可以随时打破并在任何地方检查你的程序的价值。

答案 1 :(得分:1)

  “是的,”哈利说。 “在。 。 。在一分钟内。我会清楚这一点。“   他把破碎的碗放在地板上。罗恩点点头,离开了。 “   Reparo,“哈利嘟,道,用魔杖指着破碎的碎片,他们一起飞回来,好像新的一样,但没有把murtlap精华重新转向碗。 - 哈利波特和Pheonix的命令

一旦keyboard interrupt被提出,该信息就会丢失 - try / catch允许程序恢复,但之前发生的事情将永远丢失[1]

Luckily, the keyboard-interrupt is actually a signal at the c-level - 你可以intercept and handle it separately, if you'd like totracebackintrospect模块应该有用

对于简单的黑客攻击,这应该没问题,但我一般都要谨慎使用它,基于来自信号docs的this comment(依赖于实现):

  

我们仍然存在一些问题,即在某些实现中发出信号      由键盘生成的(例如SIGINT)被传递给所有人      线程(例如SGI),而在其他线程(例如Solaris)中,这样的信号是      交付给一个随机线程(中间可能性会      将它传递给主线程 - POSIX?)。现在,我们有      一个适用于所有三种情况的工作实现 -      如果getpid()与main中的相同,则处理程序忽略信号      线。 XXX这是一个黑客。

<强>脚注

[1]好的,不,不是。你可以使用足够的introspection在python中做任何事情,但这是一个糟糕的主意,并不符合我的引用。如果你真的想要做一些可怕的事情,这些人已经为你做了这件事:https://github.com/ajalt/fuckitpy