pythonのマルチプロセッシングパッケージをこのように使用しようとしています:
featureClass = [[1000,k,1] for k in drange(start,end,step)] #list of arguments
for f in featureClass:
pool .apply_async(worker, args=f,callback=collectMyResult)
pool.close()
pool.join
プールのプロセスから、その結果を返すのに60秒以上かかるプロセスを待たないようにしたいと思います。それは可能ですか?
これは、worker
関数を変更せずにこれを実行できる方法です。次の2つの手順が必要です。
maxtasksperchild
オプションを使用してmultiprocessing.Pool
に渡すことができるため、タスクが実行されるたびにプール内のワーカープロセスが確実に再起動されます。worker
を呼び出し、そのスレッドからの結果をtimeout
秒間待機します。プロセスはデーモンスレッドの終了を待たずに終了するため、デーモンスレッドの使用は重要です。タイムアウトの期限が切れた場合は、ラッパー関数を終了(または中止-自分次第)し、タスクを終了します。maxtasksperchild=1
を設定したため、Pool
によってワーカーが終了しますプロセスし、新しいものを開始します。これは、実際の作業を行っているバックグラウンドスレッドもデーモンスレッドであり、そのスレッドが実行しているプロセスがシャットダウンされたために中止されることを意味します。
import multiprocessing
from multiprocessing.dummy import Pool as ThreadPool
from functools import partial
def worker(x, y, z):
pass # Do whatever here
def collectMyResult(result):
print("Got result {}".format(result))
def abortable_worker(func, *args, **kwargs):
timeout = kwargs.get('timeout', None)
p = ThreadPool(1)
res = p.apply_async(func, args=args)
try:
out = res.get(timeout) # Wait timeout seconds for func to complete.
return out
except multiprocessing.TimeoutError:
print("Aborting due to timeout")
raise
if __name__ == "__main__":
pool = multiprocessing.Pool(maxtasksperchild=1)
featureClass = [[1000,k,1] for k in range(start,end,step)] #list of arguments
for f in featureClass:
abortable_func = partial(abortable_worker, worker, timeout=3)
pool.apply_async(abortable_func, args=f,callback=collectMyResult)
pool.close()
pool.join()
タイムアウトする関数はmultiprocessing.TimeoutError
を発生させます。これは、タイムアウトが発生したときにコールバックが実行されないことを意味します。これが許容できない場合は、except
を呼び出すのではなく、abortable_worker
のraise
ブロックを変更して何かを返すだけです。
また、すべてのタスク実行後にワーカープロセスを再起動すると、オーバーヘッドが増加するため、Pool
のパフォーマンスに悪影響を及ぼすことにも注意してください。あなたはあなたのユースケースのためにそれを測定し、トレードオフが仕事を中止する能力を持つことの価値があるかどうかを見るべきです。それが問題である場合、外部から殺すのではなく、実行時間が長すぎる場合はworker
を協調的に中断するなど、別のアプローチを試す必要があるかもしれません。このトピックをカバーするSOに関する質問がたくさんあります。
gevent.Timeoutを使用して、実行中のワーカーの時間を設定できます。 geventチュートリアル
from multiprocessing.dummy import Pool
#you should install gevent.
from gevent import Timeout
from gevent import monkey
monkey.patch_all()
import time
def worker(sleep_time):
try:
seconds = 5 # max time the worker may run
timeout = Timeout(seconds)
timeout.start()
time.sleep(sleep_time)
print "%s is a early bird"%sleep_time
except:
print "%s is late(time out)"%sleep_time
pool = Pool(4)
pool.map(worker, range(10))
output:
0 is a early bird
1 is a early bird
2 is a early bird
3 is a early bird
4 is a early bird
8 is late(time out)
5 is late(time out)
6 is late(time out)
7 is late(time out)
9 is late(time out)