6

Debian で単一スレッドの Python 2.7 デーモン/サービスを実行しています。特定のハードウェア機能を無効にする重要なクリーンアップ コードがいくつかあります。

import sys
import atexit
import signal
from my_job import give_high_fives
from my_cleanup import prevent_the_apocalypse

atexit.register(prevent_the_apocalypse)
signal.signal(signal.SIGTERM, prevent_the_apocalypse)
signal.signal(signal.SIGHUP, prevent_the_apocalypse)
try:
    while True:
        give_high_fives()
finally:
    prevent_the_apocalypse()

これは妄想的に見えますし、クリーンアップ コードを何度も呼び出すのも好きではありません。現在、クリーンアップが で 3 回または 4 回呼び出されているようSIGTERMです。

prevent_the_apocalypse考えられるすべての終了条件で正確に 1 回だけの方法はありますか?

4

2 に答える 2

6

Python で正しいデーモンを作成するのは困難です。実際、どの言語でも難しいです。PEP 3143で問題が説明されています。

詳細のdaemonほとんどはモジュールにまとめられているため、正しく理解する必要はありません。それを使えば、クリーンアップコードを追加するのが非常に簡単になります。

1つのオプションは、サブクラスdaemon.DaemonContext化してそこに置くことです。例えば:

class MyDaemonContext(daemon.DaemonContext):
    def close(self):
        if not self.is_open:
            return
        prevent_the_apocalypse()
        super(MyDaemonContext, self).close()

with MyDaemonContext():
    while True:
        give_high_fives()

モジュールは、メソッドdaemonをスキップせずに、構成したことを実行するようにシグナルハンドラーを既にセットアップしています。close(closeは、必要に応じて、コンテキスト__exit__内、atexitメソッド内、または場合によっては別の場所で、1 回だけ実行されます。)

closeサブクラス化する代わりに、一部のシグナルがスキップし、他のシグナルがスキップしない、より複雑なものが必要な場合は、signal_map適切に設定してください。

于 2013-10-09T17:50:13.863 に答える
-1

シグナル ハンドラーは、グローバル変数を true に設定するだけです。次に、メイン ループでその変数をチェックし、それが true の場合はブレークアウトし、終了時にクリーンアップ ハンドラーを実行します。

于 2013-10-09T17:51:26.670 に答える