我做很多项目编码问题,而Python是我的首选语言。许多程序通常需要永远完成,因此我正在努力实施一些可以帮助提供有关程序状态的诊断信息的内容:当发生KeyboardInterrupt
时,我希望能够打印程序运行的时间,并且有些信息可以帮助我弄清楚它可能需要多长时间。
当您击中Ctrl-C
时,KeyboardInterrupt
的问题仍在为我退出程序...我认为这与该代码的结构有很大关系,或者希望在Python I中使用某些东西还没有找到。
我希望我的代码在抓住KeyboardInterrupt
后立即在同一行中恢复。
以下是此代码的外观:
try:
...
...
... #I interrupt code here and hopefully keep going!
...
...
except KeyboardInterrupt:
...
finally:
...
我希望有人能理解这样做的目的,并可以帮助我找到一种方法,或者围绕这种丑陋的方式来召集从运行代码中休息的方式。
一般而言,在试验块中触发例外后,您永远无法将执行返回到特定的代码段,鉴于例外可能会发生在某个地方,并且有许多其他受影响的状态其他线程中的其他副作用。虽然您的程序可能不是这种情况,但鉴于没有一般解决方案可以在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
)终止程序。如果您合并了此功能,您基本上可以随时断开并在任何地方检查程序的值。
"是的,"哈利说。"在 。。。在一分钟内。我只会清理这个。" 他指示地板上的碗砸碎了。罗恩点点头,离开。" reparo,"哈利喃喃地说,将魔杖指着他们飞回的破碎的碎片,就像新的一样,但没有将穆尔特拉普的本质转向碗。 - 哈利·波特和菲尼克斯的顺序
一旦键盘中断了,就会丢失信息 - 尝试/捕获允许程序恢复,但是在此之前发生的事情永远丢失了[1]
。
幸运的是,键盘间断实际上是C级信号 - 如果您愿意,您可以单独截取并分别处理它。追溯和内省模块应有用
对于简单的hacks,这应该很好,尽管我通常会根据信号文档的这一评论(实现依赖)来使用它:
:我们仍然有一个问题,即在某些实施信号中 由键盘(例如Sigint)生成的 线程(例如SGI),而在其他线程(例如Solaris)中,此类信号为 传递到一个随机线程(中间可能性将 将其传递到主线程 - posix?)。现在,我们有 在所有三种情况下都起作用的工作实施 - 如果getPid()与主中的getPid()不同,则处理程序会忽略信号 线。xxx这是一个黑客。
脚注
[1]
好吧,不。您可以在Python中使用足够的内省进行任何操作,但这是一个可怕的主意,不符合我的报价。如果您真的想做可怕的事情,这些人就为您做了:https://github.com/ajalt/fuckitpy