30

有没有办法在运行的 Python 脚本被其他脚本、键盘中断等杀死之前运行最后一个命令?

4

5 回答 5

43
import time

try:
    time.sleep(10)
finally:
    print "clean up"
    
clean up
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt

如果需要捕捉其他操作系统级别的中断,看信号模块:

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)
于 2009-05-30T20:29:50.813 回答
13

您可以使用该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()

因此,您可能还想注册一个信号处理程序。

于 2009-05-30T20:32:14.617 回答
10
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
于 2009-05-30T20:24:34.257 回答
8

向“未知”道歉,因为他们接受了他们的答案并进行了更正,就好像这是我自己的答案一样,但我的编辑被拒绝了。

批准的答案包含将导致段错误的错误。

您不能在信号处理程序中使用 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 但通常不建议这样做,因为程序状态可能会导致您创建无限循环。

于 2016-01-03T09:55:32.433 回答
6

使用 atexit 模块注册一个将在最后调用的函数。

import atexit
atexit.register(some_function)
于 2009-05-30T20:32:20.683 回答