2017-05-06 9 views
1

私はクラスを適切に閉鎖したいと思います。特に、私のメインプロセスが外部イベント(例えば:SIGTERM)から殺されたとしても、それを閉じたいと思う。正しい閉鎖を保証する方法

「異常に」殺された場合、コンテキストマネージャーとatexitは呼び出されません。だから私はイベントをキャプチャして特定のクリーンアップコードを実行するために信号を使用しようとしてきました。

しかし今、私はpythonがさまざまなタイプの出口をきれいにする方法の雑草に入っています。たとえば、signal.SIGTERMを捕捉して自分自身のハンドラを追加することができますが、完了したらデフォルトのハンドラを呼び出す方法はわかりません。しかし、専門家ではないので、自分のコードで適切なシステム出口を私の図書館に引き継ぐことは不愉快です。

(細目:。私は棚上げして、棚を閉じていない場合、それはロックされ、非開放可能な状態のままになります使用している - 基本的に使用できない)

私は、これはあまりにもハードいるのでしょうか?私はきちんと整理して、深い専門知識を必要とすべきではないと確信しています。

また、信号をキャプチャしてシステム終了を引き継ぐ必要がある場合は、単にクリーンアップコードを実行できますか?他のハンドラがSIG_DFLの場合は、sys.exit()を実行します。それは危険だと思うけど、それは大丈夫ですか?

私の現在のコード:

def reg_sig(signum): 
    old_handler = signal.getsignal(signum) 

    def sighandler(signum, frame): 
     close_open_objects() # <== my custom code 
     if callable(old_handler): 
      old_handler() 
     else: 
      # What goes here? 
      # do_default_handler() # <- this seems ideal 
      # or 
      # sys.exit() 

    try: 
     # I'm not sure what signals might be called so I register a bunch. 
     signal.signal(signum, sighandler) 
    except Exception as err: 
     pass 

# Register signals 
for sig in [signal.SIGHUP, signal.SIGINT, signal.SIGQUIT, signal.SIGABRT, 
      signal.SIGKILL,signal.SIGTERM]: 
    reg_sig(sig) 
+1

シグナルを受信するプロセスがSIGKILL(およびSIGSTOP)を捕まえることはできません。例えば、コンピュータから電源を引き出すなど、他にも「外部イベント」があります。どのような敵対的環境でコーディングしているのですか?すべての信号を捕まえることが必要ですか? –

+0

可能な重複:https://stackoverflow.com/questions/23468042/the-invocation-of-signal-handler-and-atexit-handler-in-python#23468485 –

+0

@MathiasRav - OPはこれが ' 「棚」データベース。 – tdelaney

答えて

3

簡単な解決策は、atexitをを使用してsys.exit(0)を呼び出すシグナルハンドラを登録することです。これはシグナルの場合に通常返されるものからプロセス終了コードを変更することに注意してください。 a related answer

+0

質問 - この出口は本質的に通常のSIGTERM(または他の)終了と同等ですか?私の心配は、私がSIGTERMや別のシグナルを引き継ぐことによって、私が理解していない方法でPythonの終了動作を変更することです。 SIGTERMが常にスタックトレースを出力したり、イベントを登録したり、mommyに家に帰ったりする場合はどうなりますか?私は殺害事件の所有権を取ることに少し心配しています。 –

+0

ライブラリコンポーネントが同じプロセス内の他のコンポーネントと干渉しないようにシグナルを処理できるようにするには、異なるシグナルハンドラを調整する機能を追加する必要があります。 Pythonの標準ライブラリにはそのようなことはないので、アプリケーションに単一のシグナルハンドラをインストールし、コンポーネントが何らかの形でシグナルハンドラにフックできるようにする必要があります。一部のコンポーネント**は、killイベントの所有権を取得する必要があります - 好ましくは、シグナル処理専用のコンポーネントです。 –

+0

Ok - これはまさに私が手に入れたものです。ちょうど確認する - 信号をキャプチャする方法はありません、自分のことを行い、そしてそれを再びPythonのデフォルトのシグナルハンドラに戻しますか? –