如何在Python中被杀之前运行最后一个函数?

dan*_*dan 23 python function interrupt exit

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

Unk*_*own 33

import time

try:
    time.sleep(10)
finally:
    print "clean up"

clean up
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt
Run Code Online (Sandbox Code Playgroud)

如果需要捕获其他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)
Run Code Online (Sandbox Code Playgroud)

  • 我不知道为什么你选择那个特定的集合,但SIGBREAK不适用于非Windows Pythons,而SIGILL是SIGSEGV可能不是你想要陷阱的信号而没有一个很好的理由. (13认同)
  • @Dave只是一个例子.并且它可以决定他想要捕获哪些中断. (5认同)
  • 是`sys.exit(0)`必要吗?无论如何,我认为python在你的功能完成后退出.你用它来表明它是一个处理终止? (2认同)
  • -1 表示奇怪且任意的信号集,正如@Dave 所指出的。使用“SIGTERM”是有意义的(因为它的目的是指示进程退出),并且使用“SIGUSR1”是合理的(因为它用于用户定义的操作),但是在那里使用“SIGILL”之类的东西是不合逻辑的。另外,这只是部分回答了问题;它不会处理脚本被键盘中断杀死的情况,这是问题中可能包含的情况。 (2认同)

jbr*_*ric 11

你可以使用该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)
Run Code Online (Sandbox Code Playgroud)

您还可以将位置和关键字参数传递给要在程序终止时调用的函数.

请注意,文档中列出了一些不会调用处理程序的情况:

注意:当程序被Python未处理的信号杀死,检测到Python致命内部错误或被调用时,不会调用通过此模块注册的函数os._exit().

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


Dav*_*ave 8

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
Run Code Online (Sandbox Code Playgroud)


San*_*hal 6

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

import atexit
atexit.register(some_function)
Run Code Online (Sandbox Code Playgroud)


Stu*_*t M 6

向'未知'道歉,因为他们回答并纠正它,好像这是我自己的答案,但我的编辑被拒绝了.

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

你不能在信号处理程序中使用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)
Run Code Online (Sandbox Code Playgroud)

如果目标平台是Windows,则可以使用SIGBREAK.

根据用例和在发生致命错误时需要清理 - 您可以添加SIGSEGV和SIGILL,但通常不建议这样做,因为程序状态可能会导致您创建无限循环.