如果从函数内部执行,带有“apply_async”的多处理池啥也不做

Posted

技术标签:

【中文标题】如果从函数内部执行,带有“apply_async”的多处理池啥也不做【英文标题】:Multiprocessing pool with "apply_async" does nothing if executed from inside a function如果从函数内部执行,带有“apply_async”的多处理池什么也不做 【发布时间】:2019-10-24 08:31:21 【问题描述】:

我正在尝试使用 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】:

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

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 协议来序列化要发送到其他进程的数据。 pickle 协议只能序列化***函数,不能序列化嵌套函数。

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

【讨论】:

谢谢!但是,如果我不调用get(),为什么它会静默失败? 由于您没有声明结果,它只会忽略它。原因可能是您想要异步执行某些事情,无论它是否成功。您还可以查看concurrent.futures 模块,它具有类似但更清晰的 API。 作为用户,我希望收到有关酸洗过程失败的通知,因为它不是我实际功能的一部分。不过没关系,谢谢解释。 通常异步调用不会在设计上造成副作用。原因是异步调用不应影响应用程序的执行流程。开发人员有责任决定是否检查异步执行的作业的结果。如果您不想阻止线程等待结果,您可以随时使用回调函数记录您提交的作业的结果/异常。

以上是关于如果从函数内部执行,带有“apply_async”的多处理池啥也不做的主要内容,如果未能解决你的问题,请参考以下文章

python multiprocessing.pool.apply_async 占用内存多 解决方法

如何从 pool.apply_async 调用中累积结果?

在 python2.7 中使用 pool.apply_async 不将值插入 MySQL 表

使用带有内部库的 maven 构建 android 项目

从iframe外部调用iframe内部的函数[重复]

python 多进程中的p.apply_async()