簡體   English   中英

Python multiprocessing.Queue 未從分叉進程接收放置

[英]Python multiprocessing.Queue not receiving puts from forked processes

我正在創建固定數量的分叉子進程並嘗試讓它們通過multiprocessing.Queue返回結果。 這導致了一些意想不到的行為。

import multiprocessing
import os

def main():
    n_workers = 4

    q = multiprocessing.Queue(n_workers)

    for i in range(n_workers):
        if os.fork() == 0:
            print(f"child {i} put {i}")
            q.put(i)
            print(f"child {i} exiting")
            os._exit(0)

    for i in range(n_workers):
        res = q.get()
        print(f"parent got {res}")

    print("parent exiting")


if __name__ == "__main__":
    main()

當我運行它時,所有的孩子都將他們的結果排入隊列並終止,但父進程掛起:

child 0 put 0                                                                              │
child 1 put 1                                                                              │
child 2 put 2                                                                              │
child 3 put 3                                                                              │
child 0 exiting                                                                            │
child 1 exiting                                                                            │
child 2 exiting                                                                            │
child 3 exiting                                                                            │
parent got 0

問題是在將數據放入隊列后立即調用os._exit(0)

多處理文檔解釋了如何將數據添加到隊列中:

當一個對象被放入隊列時,該對象被腌制,后台線程稍后將腌制的數據刷新到底層管道。

因為進程是分叉的,所以調用os._exit(0)是必要的(而不是sys.exit(0) ),但它不做任何清理 如果后台線程還沒有刷新數據,就會丟失!

解決方案是調用close()后跟join_thread()

import multiprocessing
import os

def main():
    n_workers = 4

    q = multiprocessing.Queue(n_workers)

    for i in range(n_workers):
        if os.fork() == 0:
            print(f"child {i} put {i}")
            q.put(i)
            print(f"child {i} exiting")

            q.close()  # indicate nothing else will be queued by this process
            q.join_thread()  # wait for the background thread to flush the data

            os._exit(0)

    for i in range(n_workers):
        res = q.get()
        print(f"parent got {res}")

    print("parent exiting")


if __name__ == "__main__":
    main()

暫無
暫無

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

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