[英]Multiprocessing Queue.get() hangs
我正在嘗試實現基本的多處理,我遇到了一個問題。 python腳本附在下面。
import time, sys, random, threading
from multiprocessing import Process
from Queue import Queue
from FrequencyAnalysis import FrequencyStore, AnalyzeFrequency
append_queue = Queue(10)
database = FrequencyStore()
def add_to_append_queue(_list):
append_queue.put(_list)
def process_append_queue():
while True:
item = append_queue.get()
database.append(item)
print("Appended to database in %.4f seconds" % database.append_time)
append_queue.task_done()
return
def main():
database.load_db()
print("Database loaded in %.4f seconds" % database.load_time)
append_queue_process = Process(target=process_append_queue)
append_queue_process.daemon = True
append_queue_process.start()
#t = threading.Thread(target=process_append_queue)
#t.daemon = True
#t.start()
while True:
path = raw_input("file: ")
if path == "exit":
break
a = AnalyzeFrequency(path)
a.analyze()
print("Analyzed file in %.4f seconds" % a._time)
add_to_append_queue(a.get_results())
append_queue.join()
#append_queue_process.join()
database.save_db()
print("Database saved in %.4f seconds" % database.save_time)
sys.exit(0)
if __name__=="__main__":
main()
AnalyzeFrequency分析文件中單詞的頻率, get_results()
返回所述單詞和頻率的排序列表。 列表非常大,可能有10000個項目。
然后將此列表傳遞給add_to_append_queue
方法,該方法將其添加到隊列中。 process_append_queue逐個獲取項目並將頻率添加到“數據庫”。 此操作比main()
的實際分析需要更長的時間,因此我嘗試對此方法使用單獨的過程。 當我嘗試使用線程模塊執行此操作時,一切正常,沒有錯誤。 當我嘗試使用Process時,腳本掛起在item = append_queue.get()
。
有人可以解釋一下這里發生了什么,也許可以指導我解決問題嗎?
所有答案都贊賞!
UPDATE
泡菜錯誤是我的錯,這只是一個錯字。 現在我在多處理中使用Queue類,但append_queue.get()方法仍然掛起。 新代碼
import time, sys, random
from multiprocessing import Process, Queue
from FrequencyAnalysis import FrequencyStore, AnalyzeFrequency
append_queue = Queue()
database = FrequencyStore()
def add_to_append_queue(_list):
append_queue.put(_list)
def process_append_queue():
while True:
database.append(append_queue.get())
print("Appended to database in %.4f seconds" % database.append_time)
return
def main():
database.load_db()
print("Database loaded in %.4f seconds" % database.load_time)
append_queue_process = Process(target=process_append_queue)
append_queue_process.daemon = True
append_queue_process.start()
#t = threading.Thread(target=process_append_queue)
#t.daemon = True
#t.start()
while True:
path = raw_input("file: ")
if path == "exit":
break
a = AnalyzeFrequency(path)
a.analyze()
print("Analyzed file in %.4f seconds" % a._time)
add_to_append_queue(a.get_results())
#append_queue.join()
#append_queue_process.join()
print str(append_queue.qsize())
database.save_db()
print("Database saved in %.4f seconds" % database.save_time)
sys.exit(0)
if __name__=="__main__":
main()
更新2
這是數據庫代碼:
class FrequencyStore:
def __init__(self):
self.sorter = Sorter()
self.db = {}
self.load_time = -1
self.save_time = -1
self.append_time = -1
self.sort_time = -1
def load_db(self):
start_time = time.time()
try:
file = open("results.txt", 'r')
except:
raise IOError
self.db = {}
for line in file:
word, count = line.strip("\n").split("=")
self.db[word] = int(count)
file.close()
self.load_time = time.time() - start_time
def save_db(self):
start_time = time.time()
_db = []
for key in self.db:
_db.append([key, self.db[key]])
_db = self.sort(_db)
try:
file = open("results.txt", 'w')
except:
raise IOError
file.truncate(0)
for x in _db:
file.write(x[0] + "=" + str(x[1]) + "\n")
file.close()
self.save_time = time.time() - start_time
def create_sorted_db(self):
_temp_db = []
for key in self.db:
_temp_db.append([key, self.db[key]])
_temp_db = self.sort(_temp_db)
_temp_db.reverse()
return _temp_db
def get_db(self):
return self.db
def sort(self, _list):
start_time = time.time()
_list = self.sorter.mergesort(_list)
_list.reverse()
self.sort_time = time.time() - start_time
return _list
def append(self, _list):
start_time = time.time()
for x in _list:
if x[0] not in self.db:
self.db[x[0]] = x[1]
else:
self.db[x[0]] += x[1]
self.append_time = time.time() - start_time
評論建議你試圖在Windows上運行它。 正如我在評論中所說,
如果您在Windows上運行它,它無法工作 - Windows沒有
fork()
,因此每個進程都有自己的Queue,它們彼此無關。 整個模塊由Windows上的每個進程“從頭開始”導入。 您需要在main()
創建Queue,並將其作為參數傳遞給worker函數。
雖然我刪除了所有數據庫內容,因為它與你到目前為止所描述的問題無關,所以這里充實了你需要做些什么以使其可移植。 我也刪除了daemon
,因為這通常只是一種懶惰的方式來避免干凈地關閉事物,並且通常不會再回來咬你:
def process_append_queue(append_queue):
while True:
x = append_queue.get()
if x is None:
break
print("processed %d" % x)
print("worker done")
def main():
import multiprocessing as mp
append_queue = mp.Queue(10)
append_queue_process = mp.Process(target=process_append_queue, args=(append_queue,))
append_queue_process.start()
for i in range(100):
append_queue.put(i)
append_queue.put(None) # tell worker we're done
append_queue_process.join()
if __name__=="__main__":
main()
輸出是“顯而易見”的東西:
processed 0
processed 1
processed 2
processed 3
processed 4
...
processed 96
processed 97
processed 98
processed 99
worker done
注意:因為Windows不能(不能) fork()
,所以工作進程不可能在Windows上繼承任何Python對象。 每個進程從一開始就運行整個程序。 這就是原始程序無法工作的原因:每個進程都創建了自己的Queue
,與其他進程中的Queue
完全無關。 在上面顯示的方法中,只有主進程創建一個Queue
,主進程將它(作為參數)傳遞給worker進程。
queue.Queue
是線程安全的,但不能跨進程工作。 不過,這很容易解決。 代替:
from multiprocessing import Process
from Queue import Queue
你要:
from multiprocessing import Process, Queue
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.