簡體   English   中英

python 多處理隊列實現

[英]python multiprocessing queue implementation

我無法理解如何在下面的多處理示例中實現隊列。 基本上,我希望代碼能夠:

1) 生成 2 個進程(完成)

2) 將我的 id_list 分成兩部分(完成)

3)讓每個進程遍歷打印出每個項目的列表,並且僅在完成列表后才關閉。 我知道我必須實施某種類型的排隊系統,並將其傳遞給每個工作人員,但我不確定該怎么做。 任何幫助將非常感激。

from multiprocessing import Pool,Queue
id_list = [1,2,3,4,5,6,7,8,9,10]

def mp_worker(record):
    try:  
        print record
        sleep(1)
    except: pass
    print "worker closed"

def mp_handler():
    p = Pool(processes = 2) #number of processes
    p.map(mp_worker, id_list)  #devides id_list between 2 processes, defined above
    p.close()
    p.join()

mp_handler()

注意 - 代碼打印出“worker closed”10 次。 我希望這條語句只打印兩次(每個工人打印一次,在每個工人打印出 id_list 中的 5 個數字之后)

這對我有用(在 Python 3 上)。 我沒有使用池,而是生成了自己的兩個進程:

from multiprocessing import Process, Queue
from time import sleep


id_list = [1,2,3,4,5,6,7,8,9,10]

queue = Queue()

def mp_worker(queue):

    while queue.qsize() >0 :
        record = queue.get()
        print(record)
        sleep(1)

    print("worker closed")

def mp_handler():

    # Spawn two processes, assigning the method to be executed 
    # and the input arguments (the queue)
    processes = [Process(target=mp_worker, args=(queue,)) for _ in range(2)]

    for process in processes:
        process.start()
        print('Process started')

    for process in processes:
        process.join()



if __name__ == '__main__':

    for id in id_list:
        queue.put(id)

    mp_handler()

盡管要處理的元素的長度是硬編碼的。 但它可能是 mp_worker 方法的第二個輸入參數。

使用 Pool 和 Queue 解決此問題的一種方法是


    from time import sleep
    from multiprocessing import Pool,Queue
    id_list = [1,2,3,4,5,6,7,8,9,10]

    def mp_worker(q):
        try:  
            print(q.get())
            sleep(.1)
        except: pass
        print ("worker closed")

    if __name__ == "__main__":
        q = Queue()
        p = Pool(processes = 2) #number of processes
        for x in id_list:
            q.put(x)
        p.map(mp_worker, id_list)  #devides id_list between 2 processes, defined above


您必須通過放入代碼的主要部分並在函數中通過get從隊列中讀取值來向 Quene 添加 vaules

您在那里的打印語句會誤導您——工作進程不會在函數結束時終止。 事實上,工作進程在池關閉之前一直保持活動狀態。 此外, multiprocessing已經負責將列表分解成塊並為您排隊每個任務。

至於你的另一個問題,如果你想在整個列表完成時觸發一個異步事件,通常你會向map_async傳遞一個回調。 每個塊調用一次需要對內部進行一些處理,但如果你真的想要,你可以:

def mapstar_custom(args):
    result = list(map(*args))
    print "Task completed"
    return result
...

pool._map_async(f, x, mapstar_custom, None, None, None).get()

編輯:我們似乎混淆了術語。 當我說 worker 時,我指的是池產生的進程,而您似乎指的是 Selenium 從這些進程中產生的進程(這不是您的問題)。 只打開一次 webdriver 很容易:如果你有pool.map(module.task, ...) ,那么在module.py只需執行以下操作:

# ... selenium init here ...

def task(...):
    # ... use webdriver ...

無論您分派該任務多少次,該模塊只會被池工作人員導入一次。 所以頂級 init 只會發生一次。

由於這是Python Multiprocessing Queue implementation的最高 Google 結果,我將發布一個稍微更通用的示例。

考慮以下腳本:

import time
import math
import pprint

def main():
    print('\n' + 'starting . . .' + '\n')

    startTime = time.time()
    my_list = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
    result_list = []

    for num in my_list:
        result_list.append(squareNum(num))
    # end for

    elapsedTime = time.time() - startTime

    print('result_list: ')
    pprint.pprint(result_list)
    print('\n' + 'program took ' + '{:.2f}'.format(elapsedTime) + ' seconds' + '\n')
# end function

def squareNum(num: float) -> float:
    time.sleep(1.0)
    return math.pow(num, 2)
# end function

if __name__ == '__main__':
    main()

該腳本聲明 10 個浮點數,對它們進行平方(在每個平方上休眠 1 秒以模擬一些重要過程),然后將結果收集到一個新列表中。 運行大約需要 10 秒。

這是使用Multiprocessing ProcessQueue的重構版本:

from multiprocessing import Process, Queue
import time
import math
from typing import List
import pprint


def main():
    print('\n' + 'starting . . .' + '\n')

    startTime = time.time()
    my_list = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
    result_list = []

    multiProcQueue = Queue()

    processes: List[Process] = []
    for num in my_list:
        processes.append(Process(target=squareNum, args=(num, multiProcQueue,)))
    # end for

    for process in processes:
        process.start()
    # end for

    for process in processes:
        process.join()
    # end for

    while not multiProcQueue.empty():
        result_list.append(multiProcQueue.get())
    # end for

    elapsedTime = time.time() - startTime

    print('result_list: ')
    pprint.pprint(result_list)
    print('\n' + 'program took ' + '{:.2f}'.format(elapsedTime) + ' seconds' + '\n')
# end function

def squareNum(num: float, multiProcQueue: Queue) -> None:
    time.sleep(1.0)
    result = math.pow(num, 2)
    multiProcQueue.put(result)
# end function

if __name__ == '__main__':
    main()

該腳本運行大約 1 秒。 據我所知,這是讓多個進程將結果並行寫入同一數據結構的最干凈的方法。 我希望文檔https://docs.python.org/3/library/multiprocessing.html有這樣的示例。

請注意,結果列表的順序通常與輸入列表的順序不匹配,如果必須保持順序,則需要采用不同的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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