Como executar uma última função antes de ser morto em Python?
Pergunta
Existe alguma maneira de executar um último comando antes de um Python script em execução é interrompida por ser morto por algum outro roteiro, teclado interrupção etc.
Solução
import time
try:
time.sleep(10)
finally:
print "clean up"
clean up
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
KeyboardInterrupt
Se você precisa pegar outras interrupções de nível OS, olhar para o módulo de sinal:
http://docs.python.org/library/signal.html
Signal Exemplo
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)
Outras dicas
Você pode usar o módulo atexit
. Com ele, você pode registrar uma função que será chamado no término do programa. Um exemplo de aqui: 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)
Você também pode passar parâmetros posicionais e à função que deseja chamar no término do programa.
Note que existem algumas circunstâncias referidas nos documentos em que o manipulador não será chamado:
Nota ??strong>: As funções registadas através deste módulo não são chamados quando o programa é morto por um sinal não tratado por Python, quando um erro interno fatal Python é detectado, ou quando
os._exit()
é chamado.
Como tal, você também pode querer registrar um manipulador de sinal.
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
Com desculpas a 'Desconhecido' para tomar sua resposta e corrigi-lo como se fosse minha própria resposta, mas as minhas edições foram rejeitadas.
A resposta aprovado contém um erro que irá causar um segfault.
Você não pode usar sys.exit () em um manipulador de sinal, mas você pode usar os._exit modo que se torna:
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 pode ser usado se a plataforma de destino é o Windows.
Dependendo do caso de uso ea necessidade de limpeza em caso de erros fatais -. Você pode adicionar SIGSEGV e SIGILL mas geralmente isso não é aconselhável uma vez que o estado do programa pode ser tal que você cria um loop infinito
Use o módulo atexit para registrar uma função que será chamada no final.
import atexit
atexit.register(some_function)