1

私はデーモンを初めて使用し、メイン スクリプトをデーモンにする方法を知りたいと思っていました。

デーモンを作成してバックグラウンドで実行したいメインスクリプトがあります。

 main.py

     def requestData(information):
         return currently_crunched_data()

     while True:
          crunchData()

ループの実行中に、このデーモンに対して requestData 関数を使用できるようにしたいと考えています。デーモンや、スクリプトをデーモンに変換する方法にあまり詳しくありません。

ただし、デーモンには独自のループ (daemon.requestLoop()) があるため、cruncData ループ用とデーモン要求レシーバー用の 2 つのスレッドを作成する必要があると思います。

私は現在、これを行うために Pyro を検討しています。ループが他のプロセス(私が推測するデーモンなど)からリクエストを受信する機能を持っている間、最終的にバックグラウンドを実行する方法を知っている人はいますか?

4

1 に答える 1

2

Python でデーモンを作成することについては、こののような質問がすでにいくつかあり、その部分にうまく答えています。

では、デーモンにバックグラウンドでの作業をさせるにはどうすればよいでしょうか?

ご想像のとおり、スレッドは明らかな答えです。しかし、考えられる複雑性が 3 つあります。


まず、シャットダウンがあります。運が良ければ、crunchDataデータの破損や (重大な) 作業の損失なしに、関数をいつでもすぐに強制終了できます。その場合:

def worker():
    while True:
        crunchData()

# ... somewhere in the daemon startup code ...
t = threading.Thread(target=worker)
t.daemon = True
t.start()

注意してt.daemonください。「デーモンスレッド」は、プログラムがデーモンであることとは何の関係もありません。これは、メイン プロセスを終了するだけですぐに強制終了されることを意味します。

しかし、crunchData殺せない場合はどうなりますか?次に、次のようなことをする必要があります。

quitflag = False
quitlock = threading.Lock()

def worker():
    while True:
        with quitlock:
            if quitflag:
                return
        crunchData()

# ... somewhere in the daemon startup code ...
t = threading.Thread(target=worker)
t.start()

# ... somewhere in the daemon shutdown code ...
with quitlock:
    quitflag = True
t.join()

の各反復にはそれほど時間がかからないと想定してcrunchDataいます。その場合はquitFlag、関数自体で定期的に確認する必要があります。


その間、バックグラウンド スレッドが生成しているデータにリクエスト ハンドラがアクセスする必要があります。そこでも何らかの同期が必要になります。

明らかなことは、別のを使用することですLockcrunchDataしかし、そのデータに頻繁に書き込んでいる可能性は十分にあります。一度に 10 秒間ロックを保持すると、リクエスト ハンドラは 10 秒間ブロックする可能性があります。しかし、ロックの取得と解放を 100 万回繰り返すと、実際の作業よりも時間がかかる可能性があります。

代替手段の 1 つは、データをダブル バッファリングすることです。crunchData新しいコピーに書き込みを行い、それが完了したら、簡単にロックを取得して を設定しcurrentData = newDataます。

ユースケースによってはQueue、 、ファイル、またはその他のものがさらに単純になる場合があります。


最後に、crunchDataおそらく多くの CPU 作業を行っています。リクエスト ハンドラーが CPU の作業をほとんど行わないようにする必要があります。そうしないと、2 つのスレッドが GIL をめぐって競合するため、各リクエストがかなり遅くなります。通常、これは問題ありません。そうである場合は、 a のmultiprocessing.Process代わりに a を使用しますThread(これにより、2 つのプロセス間でのデータの共有または受け渡しが少し複雑になりますが、それでもそれほど悪くはありません)。

于 2013-10-25T23:18:17.120 に答える