繁体   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