1. ホーム
  2. python

[解決済み] pythonのマルチプロセッシングプールでキーボード割り込み

2022-04-30 05:39:44

質問

Python のマルチプロセッシングプールで KeyboardInterrupt イベントを処理するにはどうすればよいですか?以下は簡単な例です。

from multiprocessing import Pool
from time import sleep
from sys import exit

def slowly_square(i):
    sleep(1)
    return i*i

def go():
    pool = Pool(8)
    try:
        results = pool.map(slowly_square, range(40))
    except KeyboardInterrupt:
        # **** THIS PART NEVER EXECUTES. ****
        pool.terminate()
        print "You cancelled the program!"
        sys.exit(1)
    print "\nFinally, here are the results: ", results

if __name__ == "__main__":
    go()

上記のコードを実行すると KeyboardInterrupt を押したときに発生します。 ^C しかし、その時点でプロセスは単にハングアップし、私はそれを外部で殺す必要があります。

を押せるようにしたい。 ^C を実行すると、すべてのプロセスが優雅に終了します。

解決方法は?

これはPythonのバグです。 threading.Condition.wait() で条件待ちの場合、KeyboardInterrupt が送信されない。 再現してください。

import threading
cond = threading.Condition(threading.Lock())
cond.acquire()
cond.wait(None)
print "done"

KeyboardInterrupt の例外は wait() が戻るまで配信されず、wait() は決して戻らないので、割り込みは発生しない。 KeyboardInterrupt はほぼ確実に条件待ちを中断するはずです。

なお、タイムアウトを指定した場合はそうならず、cond.wait(1)はすぐに割り込みを受信してしまいます。 そこで、回避策として、タイムアウトを指定する方法があります。 そのためには、以下のように置き換えます。

    results = pool.map(slowly_square, range(40))

    results = pool.map_async(slowly_square, range(40)).get(9999999)

などを使用します。