29.8. atexit — 終了ハンドラ


atexit モジュールは、クリーンアップ関数の登録およびその解除を行う関数を定義します。登録された関数はインタプリタの通常終了時に自動的に実行されます。atexit はそれら関数を登録した順と 逆に 実行します; ABC の順に登録した場合、インタプリタ終了時に CBA の順に実行されます。

注意: このモジュールを使用して登録された関数は、プログラムが Python が扱わないシグナルによって kill された場合、Python 内部で致命的なエラーが検出された場合、あるいは os._exit() が呼び出された場合は実行されません。

atexit.register(func, *args, **kargs)

func を終了時に実行する関数として登録します。func に渡す引数は register() の引数として指定しなければなりません。同じ関数を同じ引数で複数回登録できます。

通常のプログラムの終了時、例えば sys.exit() が呼び出されるとき、あるいは、メインモジュールの実行が完了したときに、登録された全ての関数を、最後に登録されたものから順に呼び出します。通常、より低レベルのモジュールはより高レベルのモジュールより前に import されるので、後で後始末が行われるという仮定に基づいています。

終了ハンドラの実行中に例外が発生すると、(SystemExit 以外の場合は)トレースバックを表示して、例外の情報を保存します。全ての終了ハンドラに動作するチャンスを与えた後に、最後に送出された例外を再送出します。

この関数は func を返し、これをデコレータとして利用できます。

atexit.unregister(func)

func をインタプリタ終了時に実行される関数のリストから削除します。unregister() で削除されると、func は、たとえ複数個登録されていてもインタプリタ終了時に呼び出されないことが保証されます。func が登録されていない場合、unregister() は何もせず、何も通知しません。

参考

readline モジュール

readline ヒストリファイルを読み書きするための atexit の有用な例です。

29.8.1. atexit の例

次の簡単な例では、あるモジュールを import した時にカウンタを初期化しておき、プログラムが終了するときにアプリケーションがこのモジュールを明示的に呼び出さなくてもカウンタが更新されるようにする方法を示しています。

try:
    with open("counterfile") as infile:
        _count = int(infile.read())
except FileNotFoundError:
    _count = 0

def incrcounter(n):
    global _count
    _count = _count + n

def savecounter():
    with open("counterfile", "w") as outfile:
        outfile.write("%d" % _count)

import atexit
atexit.register(savecounter)

register() に指定した位置引数とキーワード引数は登録した関数を呼び出す際に渡されます:

def goodbye(name, adjective):
    print('Goodbye, %s, it was %s to meet you.' % (name, adjective))

import atexit
atexit.register(goodbye, 'Donny', 'nice')

# or:
atexit.register(goodbye, adjective='nice', name='Donny')

デコレータ として利用する例:

import atexit

@atexit.register
def goodbye():
    print("You are now leaving the Python sector.")

デコレータとして利用できるのは、その関数が引数なしで呼び出された場合に限られます。