[解決済み] PythonでCtrl+C / SIGINTをキャッチしてマルチプロセスを優雅に終了させる [重複] [重複
2023-04-09 15:28:03
質問
をキャッチするにはどうすればよいのでしょうか? Ctrl + C をマルチプロセスPythonプログラムで実行し、すべてのプロセスを優雅に終了するために、私はunixとWindowsの両方で動作するソリューションが必要です。私は以下を試してみました。
import multiprocessing
import time
import signal
import sys
jobs = []
def worker():
signal.signal(signal.SIGINT, signal_handler)
while(True):
time.sleep(1.1234)
print "Working..."
def signal_handler(signal, frame):
print 'You pressed Ctrl+C!'
# for p in jobs:
# p.terminate()
sys.exit(0)
if __name__ == "__main__":
for i in range(50):
p = multiprocessing.Process(target=worker)
jobs.append(p)
p.start()
そしてそれは一応うまくいっているのですが、正しい解決策とは思えません。
どのように解決するのですか?
以前に承認された解決策
にはレースコンディションがあり、それは
map
と
async
という関数があります。
正しい処理方法として
Ctrl+C
/
SIGINT
と
multiprocessing.Pool
にすることです。
-
プロセスを無視するようにする
SIGINT
プロセスの前にPool
が作成されます。このようにして作成された子プロセスはSIGINT
ハンドラを継承する。 -
元に戻す
SIGINT
ハンドラの後、親プロセスでPool
が作成された後、親プロセスの -
使用する
map_async
とapply_async
をブロックするのではなくmap
とapply
. - デフォルトのブロッキングでは全てのシグナルを無視して待機するため、タイムアウトで結果を待ちます。これはPythonのバグ https://bugs.python.org/issue8296 .
組み立てる。
#!/bin/env python
from __future__ import print_function
import multiprocessing
import os
import signal
import time
def run_worker(delay):
print("In a worker process", os.getpid())
time.sleep(delay)
def main():
print("Initializng 2 workers")
original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
pool = multiprocessing.Pool(2)
signal.signal(signal.SIGINT, original_sigint_handler)
try:
print("Starting 2 jobs of 5 seconds each")
res = pool.map_async(run_worker, [5, 5])
print("Waiting for results")
res.get(60) # Without the timeout this blocking call ignores all signals.
except KeyboardInterrupt:
print("Caught KeyboardInterrupt, terminating workers")
pool.terminate()
else:
print("Normal termination")
pool.close()
pool.join()
if __name__ == "__main__":
main()
YakovShklarov が指摘したように、シグナルを無視してから親プロセスで無視を解除するまでには時間があり、その間にシグナルが失われる可能性があります。使用する
pthread_sigmask
を使用して、親プロセスでのシグナルの配信を一時的にブロックすれば、シグナルの消失を防ぐことができますが、Python-2 では利用することができません。
関連
-
[解決済み】Pythonのvirtualenvを離脱/終了/無効化する方法
-
[解決済み] PythonでSIGINTを捕捉するには?
-
[解決済み] Pythonの終了コマンド - なぜこんなにたくさんあるのか、そしてそれぞれはいつ使うべきなのか?
-
[解決済み] Pythonのexit()とsys.exit()の違いについて
-
[解決済み】プログラムを停止/終了させることなく、完全な例外トレースバックをキャッチして表示する方法は?
-
[解決済み] PILからopenCVフォーマットへの変換
-
[解決済み] 範囲指定された浮動小数点数のランダムな配列を生成します。
-
[解決済み] Pythonでマルチプロセッシングキューを使うには?
-
[解決済み] if 節の終了方法
-
[解決済み] 認証プラグイン 'caching_sha2_password' はサポートされていません。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] pythonのマルチプロセッシングプールでキーボード割り込み
-
[解決済み] Jupyterノートブックでenv変数を設定する方法
-
[解決済み] Pythonのキャッシュライブラリはありますか?
-
[解決済み] pandasのDataFrameから空のセルを含む行を削除する
-
[解決済み] Flaskで1時間ごとに関数を実行するようにスケジュールするには?
-
[解決済み] ファブリック経由でデプロイユーザとしてvirtualenvを有効化する
-
[解決済み] tensorflowのCPUのみのインストールでダイナミックライブラリ 'cudart64_101.dll' を読み込めなかった
-
[解決済み] Celeryタスクのユニットテストはどのように行うのですか?
-
[解決済み] PySparkでデータフレームのカラムをString型からDouble型に変更する方法は?
-
[解決済み] djangoのQueryDictをPythonのDictに変更するには?