multiprocessing.Queue as arg to pool worker aborts execution of worker

后端 未结 1 637
陌清茗
陌清茗 2021-01-06 13:20

I\'m actually finding it hard to believe that I\'ve run into the issue I have, it seems like it would be a big bug in the python multiprocessing module... Anyways the proble

1条回答
  •  孤街浪徒
    2021-01-06 13:43

    Problem

    When you call apply_async it returns a AsyncResult object and leaves the workload distribution to a separate thread (see also this answer). This thread encounters the problem that the Queue object can't be pickled and therefore the requested work can't be distributed (and eventually executed). We can see this by calling AsyncResult.get:

    r = p.apply_async(f,args=(q,))
    r.get()
    

    which raises a RuntimeError:

    RuntimeError: Queue objects should only be shared between processes through inheritance
    

    However this RuntimeError is only raised in the main thread once you request the result because it actually occurred in a different thread (and thus needs a way to be transmitted).

    So what happens when you do

    p.apply_async(f,args=(q,))
    

    is that the target function f is never invoked because one of it's arguments (q) can't be pickled. Therefore q never receives an item and remains empty and for that reason the call to q.get in the main thread blocks forever.

    Solution

    With apply_async you don't have to manage the result queues manually but they are readily provided to you in form of AsyncResult objects. So you can modify the code to simply return from the target function:

    from multiprocessing import Queue, Pool
    
    def f():
        return [42, None, 'hello']
    
    if __name__ == '__main__':
        q = Queue()
        p = Pool(1)
        result = p.apply_async(f)
        print(result.get())
    

    0 讨论(0)
提交回复
热议问题