簡體   English   中英

多處理Queue.get()掛起

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM