[英]Using a a manager for updating a Queue in a Python multiprocess
我正在設計一個Python多處理代碼以在可能隨着處理而更新的隊列中工作。 以下代碼有時會起作用,卡住或引發Empty錯誤。
import multiprocessing as mp
def worker(working_queue, output_queue):
while True:
if working_queue.empty() is True:
break
else:
picked = working_queue.get_nowait()
if picked % 2 == 0:
output_queue.put(picked)
else:
working_queue.put(picked+1)
return
if __name__ == '__main__':
manager = mp.Manager()
static_input = xrange(100)
working_q = manager.Queue()
output_q = mp.Queue()
for i in static_input:
working_q.put(i)
processes = [mp.Process(target=worker,args=(working_q, output_q)) for i in range(mp.cpu_count())]
for proc in processes:
proc.start()
for proc in processes:
proc.join()
results_bank = []
while True:
if output_q.empty() is True:
break
results_bank.append(output_q.get_nowait())
print len(results_bank) # length of this list should be equal to static_input, which is the range used to populate the input queue. In other words, this tells whether all the items placed for processing were actually processed.
results_bank.sort()
print results_bank
我應該使用列表作為全局變量並鎖定它,而不是使用manager.Queue()嗎?
我只是添加了一個try:
和except Exception:
來處理Empty錯誤。 現在的結果似乎是一致的。 請讓我知道如果您發現在此解決方案中我忽略的問題。
import multiprocessing as mp
def worker(working_queue, output_queue):
while True:
try:
if working_queue.empty() is True:
break
else:
picked = working_queue.get_nowait()
if picked % 2 == 0:
output_queue.put(picked)
else:
working_queue.put(picked+1)
except Exception:
continue
return
if __name__ == '__main__':
#Manager seem to be unnecessary.
#manager = mp.Manager()
#working_q = manager.Queue()
working_q = mp.Queue()
output_q = mp.Queue()
static_input = xrange(100)
for i in static_input:
working_q.put(i)
processes = [mp.Process(target=worker,args=(working_q, output_q)) for i in range(mp.cpu_count())]
for proc in processes:
proc.start()
for proc in processes:
proc.join()
results_bank = []
while True:
if output_q.empty() is True:
break
results_bank.append(output_q.get_nowait())
print len(results_bank) # length of this list should be equal to static_input, which is the range used to populate the input queue. In other words, this tells whether all the items placed for processing were actually processed.
results_bank.sort()
print results_bank
只需使用一個鎖來保護對共享數據的訪問,它就更安全了(並且可以保護您免受進程的怪異行為影響):
import multiprocessing as mp
def worker(working_queue, output_queue, lock):
while True:
shouldBeak = False
lock.acquire()
if working_queue.empty() is True:
shouldBeak = True
else:
picked = working_queue.get_nowait()
if picked % 2 == 0:
output_queue.put(picked)
else:
working_queue.put(picked+1)
lock.release()
if shouldBeak:
break
return
if __name__ == '__main__':
manager = mp.Manager()
static_input = xrange(1000)
working_q = manager.Queue()
output_q = mp.Queue()
lock = mp.Lock()
for i in static_input:
working_q.put(i)
processes = [mp.Process(target=worker,args=(working_q, output_q,lock)) for i in range(mp.cpu_count())]
for proc in processes:
proc.start()
for proc in processes:
proc.join()
results_bank = []
while True:
if output_q.empty() is True:
break
results_bank.append(output_q.get_nowait())
print len(results_bank) # length of this list should be equal to static_input, which is the range used to populate the input queue. In other words, this tells whether all the items placed for processing were actually processed.
results_bank.sort()
print results_bank
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.