为什么 multiprocessing 模块可以 pickle 调用匿名函数的函数?
Why can the multiprocessing module pickle functions that call anonymous functions?
我正在编写一些代码(运行ning 在 Mac 上),这些代码依赖于编写一长串函数并将生成的函数应用到使用多处理的列表。如果我 运行 下面的代码,我得到一个 AttributeError
,因为 multiprocessing
模块需要 pickle 函数,它不能 pickle 匿名函数。
import multiprocessing
import functools
def compose(*functions):
return functools.reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x
twox = lambda x: 2*x
funcs = [twox, twox, twox]
operation = compose(*funcs)
nums = range(10)
p = multiprocessing.Pool(processes=3)
p.map(operation, nums) ## raises an AttributeError
我明白为什么这段代码失败了。令人费解的是,如果我改为创建一个只调用操作的函数,一切都会正常进行。也就是说,下面的代码returns正确的结果是:
def wrapped_operation(x):
return operation(x)
p = multiprocessing.Pool(processes=3)
p.map(wrapped_operation, nums) ## returns [0,8,16,...]
这是为什么?在我看来,如果 Python 需要 pickle wrapped_operation,它应该 运行 进入 pickle 操作的子问题并抛出某种错误。我在这里有什么误解吗?只用非匿名函数包装匿名函数有什么问题吗?
wrapped_operation
是一个普通的命名函数。可以从父进程到子进程对它的调用。
在您的第二个变体中,匿名 operation
的创建和调用仅发生在子进程中(或者它发生在较早分叉的父进程中,具体取决于 multiprocessing
操作模式)。所以它从来没有越过进程之间的边界。
我正在编写一些代码(运行ning 在 Mac 上),这些代码依赖于编写一长串函数并将生成的函数应用到使用多处理的列表。如果我 运行 下面的代码,我得到一个 AttributeError
,因为 multiprocessing
模块需要 pickle 函数,它不能 pickle 匿名函数。
import multiprocessing
import functools
def compose(*functions):
return functools.reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x
twox = lambda x: 2*x
funcs = [twox, twox, twox]
operation = compose(*funcs)
nums = range(10)
p = multiprocessing.Pool(processes=3)
p.map(operation, nums) ## raises an AttributeError
我明白为什么这段代码失败了。令人费解的是,如果我改为创建一个只调用操作的函数,一切都会正常进行。也就是说,下面的代码returns正确的结果是:
def wrapped_operation(x):
return operation(x)
p = multiprocessing.Pool(processes=3)
p.map(wrapped_operation, nums) ## returns [0,8,16,...]
这是为什么?在我看来,如果 Python 需要 pickle wrapped_operation,它应该 运行 进入 pickle 操作的子问题并抛出某种错误。我在这里有什么误解吗?只用非匿名函数包装匿名函数有什么问题吗?
wrapped_operation
是一个普通的命名函数。可以从父进程到子进程对它的调用。
在您的第二个变体中,匿名 operation
的创建和调用仅发生在子进程中(或者它发生在较早分叉的父进程中,具体取决于 multiprocessing
操作模式)。所以它从来没有越过进程之间的边界。