代码之家  ›  专栏  ›  技术社区  ›  Delgan

如果从函数内部执行,则具有“apply\u async”的多处理池不会执行任何操作

  •  0
  • Delgan  · 技术社区  · 7 年前

    我正在尝试使用 multiprocessing 模块和更多部分 Pool.apply_async() 作用

    此代码运行良好:

    import multiprocessing
    
    def do():
        print("Foobar", flush=True)
    
    with multiprocessing.Pool(1) as pool:
        for i in range(2):
            pool.apply_async(do)
    
        pool.close()
        pool.join()
    

    这个 "Foobar" 字符串打印两次。

    然而,如果我将此代码放入函数中,然后调用此函数,则不会发生任何事情。无错误,也 “Foobar” ,程序以静默方式结束。

    import multiprocessing
    
    def test():
    
        def do():
            print("Foobar", flush=True)
    
        with multiprocessing.Pool(1) as pool:
            for i in range(5):
                pool.apply_async(do)
    
            pool.close()
            pool.join()
    
    test()
    

    为什么会这样?我正在Linux上使用Python 3.7.3。

    1 回复  |  直到 7 年前
        1
  •  4
  •   noxdafox    7 年前

    为了检索计算结果,请对代码进行以下更改。

    import multiprocessing
    
    def test():
    
        def do():
            print("Foobar", flush=True)
    
        with multiprocessing.Pool(1) as pool:
            for i in range(5):
                result = pool.apply_async(do)
    
                result.get()
    
            pool.close()
            pool.join()
    
    test()
    

    你会明白为什么“什么都没发生”。

    Traceback (most recent call last):
      File "/tmp/test.py", line 17, in <module>
        test()
      File "/tmp/test.py", line 12, in test
        result.get()
      File "/usr/lib/python3.5/multiprocessing/pool.py", line 608, in get
        raise self._value
      File "/usr/lib/python3.5/multiprocessing/pool.py", line 385, in _handle_tasks
        put(task)
      File "/usr/lib/python3.5/multiprocessing/connection.py", line 206, in send
        self._send_bytes(ForkingPickler.dumps(obj))
      File "/usr/lib/python3.5/multiprocessing/reduction.py", line 50, in dumps
        cls(buf, protocol).dump(obj)
    AttributeError: Can't pickle local object 'test.<locals>.do'    
    

    python multiprocessing.Pool 依赖于 pickle 将要发送到其他进程的数据序列化的协议。这个 泡菜 协议只能序列化顶级函数,不能序列化嵌套函数。

    查看哪些可以腌制,哪些不能检查 documentation