【问题标题】:Python multiprocessing.Queue not receiving puts from forked processesPython multiprocessing.Queue 未接收来自分叉进程的放置
【发布时间】:2020-04-11 15:05:05
【问题描述】:

我正在创建固定数量的分叉子进程并尝试让它们通过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

【问题讨论】:

    标签: python python-3.x multiprocessing fork


    【解决方案1】:

    问题是在将数据放入队列后立即调用os._exit(0)

    multiprocessing docs 解释如何将数据添加到队列中:

    当一个对象被放入队列时,该对象被腌制,然后后台线程将腌制的数据刷新到底层管道。

    因为进程是分叉的,所以必须调用os._exit(0)(而不是sys.exit(0)),但它是does not do any cleanup。如果后台线程还没有刷新数据,就会丢失!

    解决方法是先调用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()
    

    【讨论】:

      猜你喜欢
      • 2012-06-03
      • 1970-01-01
      • 2020-05-06
      • 1970-01-01
      • 2015-12-18
      • 2021-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多