2011-08-22 8 views
6

Pythonプログラムが終了したときにタスクを実行したいのですが、正常に終了した場合にのみ実行します。私が知る限り、atexitモジュールを使用すると、登録された関数は常にがプログラムの終了時に実行されることになります。正常終了時にのみ実行するように関数を登録する同様の機能はありますか?代わりに、私の出口機能が出口が正常か例外かを検出する手段がありますか?Pythonプログラムの*成功*終了時にのみ呼び出される関数を登録するにはどうすればよいですか?

ここに問題を示すコードがあります。プログラムが失敗した場合でも、プログラムが成功したことを表示します。

import atexit 

def myexitfunc(): 
    print "Program succeeded!" 

atexit.register(myexitfunc) 

raise Exception("Program failed!") 

出力:箱から出して

$ python atexittest.py 
Traceback (most recent call last): 
    File "atexittest.py", line 8, in <module> 
    raise Exception("Program failed!") 
Exception: Program failed! 
Program succeeded! 

答えて

4

atexitはあなたが何をしたいのための非常に適していません。それは主に、非常に最後の瞬間に、リソースのクリーンアップのために使われている、物事がシャットダウンされます終了します。類推すると、try/exceptの "finally"ですが、必要なのはtry/exceptの "else"です。

私が考えることができる最も簡単な方法は、スクリプトが成功したときにのみ設定するグローバルフラグを作成し続け、次にatexitに付いているすべての機能をそのフラグでチェックし、設定されています。

例:あなたは成功フラグを設定する前にsys.exit(0)を呼び出す任意のコードがある場合

_success = False 
def atsuccess(func, *args, **kwds): 
    def wrapper(): 
     if _success: 
      func(*args,**kwds) 
    atexit(wrapper) 

def set_success(): 
    global _success 
    _success = True 

# then call atsuccess() to attach your callbacks, 
# and call set_success() before your script returns 

1つの制限はあります。そのようなコードは、最初にmain関数に戻るようにリファクタリングする必要があります。そのため、set_successsys.exitを1か所に呼び出します。あなたのスクリプトでメインエントリポイントを中心に、以下のラッパのようなものを追加する必要があります、それに失敗:

try: 
    main() 
except SystemExit, err: 
    if err.code == 0: 
     set_success() 
    raise 
+0

これはおそらく私が尋ねたものを得るための最も簡単な方法です。 –

4

with声明の中で、あなたのプログラムの本体をラップし、あなただけのアクションを実行し、対応するコンテキストオブジェクトを定義します例外が発生していないとき。何かのように:

class AtExit(object): 
    def __enter__(self): 
     return self 

    def __exit__(self, exc_type, exc_value, traceback): 
     if exc_value is None: 
      print "Success!" 
     else: 
      print "Failure!" 

if __name__ == "__main__": 
     with AtExit(): 
      print "Running" 
#   raise Exception("Error") 
+0

これは、プログラム全体の最後だけでなく、プログラムの一部を終了するときに便利な方法です。これは便利なパターンなので+1します。 –

関連する問題