Как запустить одну последнюю функцию перед тем, как убить в Python? - PullRequest
22 голосов
/ 31 мая 2009

Есть ли способ выполнить одну последнюю команду до того, как запущенный скрипт Python будет остановлен из-за того, что он был убит каким-либо другим скриптом, клавиатурным прерыванием и т. Д.

Ответы [ 5 ]

32 голосов
/ 31 мая 2009
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)
10 голосов
/ 31 мая 2009

Вы можете использовать модуль 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() называется.

Таким образом, вы также можете зарегистрировать обработчик сигнала.

8 голосов
/ 31 мая 2009
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
6 голосов
/ 03 января 2016

Извиняюсь перед «Неизвестным» за то, что взял их ответ и исправил его, как будто это был мой собственный ответ, но мои изменения были отклонены.

В утвержденном ответе содержится ошибка, которая может вызвать ошибку.

Вы не можете использовать 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)

SIGBREAK может использоваться, если целевой платформой является Windows.

В зависимости от варианта использования и необходимости очистки в случае фатальных ошибок - вы можете добавить SIGSEGV и SIGILL, но обычно это не рекомендуется, поскольку состояние программы может быть таким, что вы создаете бесконечный цикл.

3 голосов
/ 31 мая 2009

Используйте модуль atexit, чтобы зарегистрировать функцию, которая будет вызываться в конце.

import atexit
atexit.register(some_function)
...