ProcessPoolExecutor 无法执行我自己的函数,但执行打印工作

Spa*_*key 2 python python-multiprocessing

代码:

if __name__ == "__main__":
    p = ProcessPoolExecutor()
    p.submit(lambda x: print(x), "something")  # doesn't work
    p.submit(print, "something")  # works fine
    time.sleep(0.5)

Run Code Online (Sandbox Code Playgroud)

为什么这是有道理的?

Gri*_*mar 5

ProcessPoolExecutor想要 pickle 函数,但由于 lambda 没有名称,因此无法找到要 pickle 的函数。

例如:

from pickle import dumps

def fun(x):
    print(x)

lmb = lambda x: print(x)

dumps(fun)  # succeeds
dumps(lmb)  # fails
Run Code Online (Sandbox Code Playgroud)

所以,这会很好地工作:

import time
from concurrent.futures import ThreadPoolExecutor


def fun(x):
    print(x)


if __name__ == "__main__":
    p = ThreadPoolExecutor()
    lmb = lambda x: print(x)
    p.submit(lmb, "lambda")  # works fine
    p.submit(fun, "local function")  # works fine
    p.submit(print, "built-in function")  # works fine
    time.sleep(0.5)
Run Code Online (Sandbox Code Playgroud)

但是,如果将 替换ThreadPoolExecutor()ProcessPoolExecutor(),则需要对函数进行 pickle,那么 lambda 将停止工作。

from concurrent.futures import ProcessPoolExecutor


if __name__ == "__main__":
    p = ProcessPoolExecutor()
    lmb = lambda x: print(x)
    future = p.submit(lmb, "lambda")  # doesn't work
    print(future.result())
Run Code Online (Sandbox Code Playgroud)

这说明酸洗时确实出现了问题,也说明了原因:

from pickle import dumps

def fun(x):
    print(x)

lmb = lambda x: print(x)

dumps(fun)  # succeeds
dumps(lmb)  # fails
Run Code Online (Sandbox Code Playgroud)

__main__是主进程,它的命名空间中没有 lambda,因为 lambda 本身是无名的。将其分配给类似的变量lmb不会改变这一点,因为 lambda 已从变量中取消引用。另外两个函数本质上在 、 命名空间中具有名称__main__,并且可以进行 pickle。

请注意,这__main__与您在以下位置测试的名称相同:

if __name__ == "__main__":
Run Code Online (Sandbox Code Playgroud)