不能多处理用户定义的代码 - 不能pickle

时间:2016-12-12 04:29:57

标签: python multiprocessing pickle

我尝试在我的任务上使用多处理,这通常意味着进行一些计算,然后传回结果。问题是定义计算的代码是由用户定义的,它是在执行之前从字符串编译的。在主进程中运行时,这可以使用exec()eval()compile()等完美运行。以下示例仅适用于f1功能,但不适用于f2。我得到'不能腌制班'代码'。这有什么办法吗?例如,使用多处理不同?还是用其他包裹?还是一些更低级的东西?由于整个应用程序的设计(即代码字符串'丢失'且只有编译版本可用),不幸地将字符串传递给进程然后在进程内编译对我来说不是一个选项。

import multiprocessing

def callf(f, a):
    exec(f, {'a': a})

if __name__ == "__main__":
    f = compile("print(a)", filename="<string>", mode="exec")
    callf(f, 10)  # this works
    process = multiprocessing.Process(target=callf, args=(f, 20))  # this does not work
    process.start()
    process.join()

更新:这是另一次尝试,实际上更接近我的实际需要。它会导致不同的错误信息,但也无法腌制该功能。

import multiprocessing

if __name__ == "__main__":
    source = "def f(): print('done')"
    locals = dict()
    exec(source, {}, locals)
    f = locals['f']
    f()  # this works
    process = multiprocessing.Process(target=f)  # this does not work
    process.start()
    process.join()

1 个答案:

答案 0 :(得分:0)

pickle无法序列化代码对象,但dill可以。有一个基于莳萝的多处理分支称为multiprocessing_on_dill,但我不知道它有多好。您也可以对代码对象进行dill编码,以使标准多处理更快乐。

import multiprocessing
import dill

def callf_dilled(f_dilled, a):
    return callf(dill.loads(f_dilled), a)

def callf(f, a):
    exec(f, {'a': a})

if __name__ == "__main__":
    f = compile("print(a)", filename="<string>", mode="exec")
    callf(f, 10)  # this works
    process = multiprocessing.Process(target=callf_dilled, 
        args=(dill.dumps(f), 20))  # now this works too!
    process.start()
    process.join()