web-dev-qa-db-ja.com

Pythonで殺される前に最後の関数を実行する方法は?

実行中のPythonスクリプトが他のスクリプト、キーボード割り込みなどによって強制終了される前に、最後の1つのコマンドを実行する方法はありますか?.

23
dan
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)
34
Unknown

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によって処理されないシグナルによって強制終了された場合、a Python致命的な内部エラーが検出された場合、または os._exit() が呼び出された場合。

そのため、シグナルハンドラーも登録することをお勧めします。

11
jbradaric
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
8
Dave

彼らの答えを自分の答えであるかのように訂正してくれたことを「不明」に謝罪しましたが、私の編集は拒否されました。

承認された回答には、セグメンテーション違反の原因となるエラーが含まれています。

シグナルハンドラーで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を追加できますが、プログラムの状態が無限ループを作成する可能性があるため、通常はお勧めしません。

6
Stuart M

Atexitモジュールを使用して、最後に呼び出される関数を登録します。

import atexit
atexit.register(some_function)
3
Sander Marechal