【发布时间】:2009-05-30 20:22:53
【问题描述】:
有没有办法在运行中的 Python 脚本被其他脚本、键盘中断等杀死之前运行最后一个命令。
【问题讨论】:
标签: python function interrupt exit
有没有办法在运行中的 Python 脚本被其他脚本、键盘中断等杀死之前运行最后一个命令。
【问题讨论】:
标签: python function interrupt exit
import time
try:
time.sleep(10)
finally:
print "clean up"
clean up
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
KeyboardInterrupt
如果需要捕捉其他OS级别的中断,看信号模块:
http://docs.python.org/library/signal.html
from signal import *
import sys, time
def clean(*args):
print "clean me"
sys.exit(0)
for sig in (SIGABRT, SIGBREAK, SIGILL, SIGINT, SIGSEGV, SIGTERM):
signal(sig, clean)
time.sleep(10)
【讨论】:
sys.exit(0) 有必要吗?我认为无论如何你的函数完成后python都会退出。你用它来表明它是一个处理过的终止吗?
SIGTERM 是有意义的(因为它的目的是指示进程退出),并且使用SIGUSR1 是合理的(因为它用于用户定义的操作),但是其中包含SIGILL 这样的东西是不合逻辑的。此外,这只是部分回答了这个问题;它不会处理脚本被键盘中断杀死的情况,这是问题中包含的一种可能性。
您可以使用atexit 模块。使用它,您可以注册一个将在程序终止时调用的函数。此处的示例:http://docs.python.org/library/atexit.html
try:
_count = int(open("/tmp/counter").read())
except IOError:
_count = 0
def incrcounter(n):
global _count
_count = _count + n
def savecounter():
open("/tmp/counter", "w").write("%d" % _count)
import atexit
atexit.register(savecounter)
您还可以将位置和关键字参数传递给您要在程序终止时调用的函数。
请注意,文档中列出了一些不会调用您的处理程序的情况:
注意:当程序被 Python 未处理的信号杀死、检测到 Python 致命内部错误或调用
os._exit()时,不会调用通过此模块注册的函数.
因此,您可能还想注册一个信号处理程序。
【讨论】:
import signal
import sys
import time
def cleanup(*args):
print 'Exiting'
sys.exit(0)
signal.signal(signal.SIGINT, cleanup)
signal.signal(signal.SIGTERM, cleanup)
while True:
time.sleep(60) # less busy loop
【讨论】:
向“未知”道歉,因为他们接受了他们的答案并更正了它,就好像这是我自己的答案一样,但我的编辑被拒绝了。
批准的答案包含会导致段错误的错误。
您不能在信号处理程序中使用 sys.exit(),但可以使用 os._exit 使其变为:
from signal import *
import os, time
def clean(*args):
print "clean me"
os._exit(0)
for sig in (SIGABRT, SIGINT, SIGTERM):
signal(sig, clean)
time.sleep(10)
如果目标平台是 Windows,则可以使用 SIGBREAK。
根据用例和在发生致命错误时清理的需要 - 您可以添加 SIGSEGV 和 SIGILL,但通常不建议这样做,因为程序状态可能会导致您创建无限循环。
【讨论】:
sys.exit()的用途?它对我来说没有段错误;我需要做什么才能看到这个段错误? “您不能在信号处理程序中使用 sys.exit()” - 它似乎对我有用;你这样做的依据是什么?由于此答案中的关键主张未经证实,因此暂时谨慎 -1。
except: 捕获SystemExit 引起的。请您详细说明“从 sys.exit() 引发异常的行为未定义”是什么意思?我不确定我是否理解你。
使用 atexit 模块注册一个将在最后调用的函数。
import atexit
atexit.register(some_function)
【讨论】: