不能多进程用户定义的代码 - 不能 pickle
can't multiprocess user defined code - cannot pickle
我尝试在我的任务中使用多处理,这通常意味着进行一些计算,然后将结果传回。问题在于定义计算的代码是由用户定义的,它是在执行之前从字符串编译而来的。当在主进程中为 运行 时,使用 exec()
、eval()
或 compile()
等非常有效。以下示例仅适用于 f1
函数,不适用于 f2
。我收到“无法腌制 class 'code'”。有什么办法解决这个问题吗?例如,以不同方式使用多处理?还是使用其他包?还是一些更底层的东西?不幸的是,由于整个应用程序的设计,将字符串传递给进程然后在进程内部编译对我来说不是一个选项(即代码字符串是 'lost' 并且只有编译版本可用)。
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()
更新:这是另一种尝试,实际上更接近我的实际需要。它会导致不同的错误消息,但也无法 pickle 函数。
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()
pickle
不能序列化代码对象但是 dill can. There is a dill-based fork of multiprocessing called 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()
我尝试在我的任务中使用多处理,这通常意味着进行一些计算,然后将结果传回。问题在于定义计算的代码是由用户定义的,它是在执行之前从字符串编译而来的。当在主进程中为 运行 时,使用 exec()
、eval()
或 compile()
等非常有效。以下示例仅适用于 f1
函数,不适用于 f2
。我收到“无法腌制 class 'code'”。有什么办法解决这个问题吗?例如,以不同方式使用多处理?还是使用其他包?还是一些更底层的东西?不幸的是,由于整个应用程序的设计,将字符串传递给进程然后在进程内部编译对我来说不是一个选项(即代码字符串是 'lost' 并且只有编译版本可用)。
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()
更新:这是另一种尝试,实际上更接近我的实际需要。它会导致不同的错误消息,但也无法 pickle 函数。
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()
pickle
不能序列化代码对象但是 dill can. There is a dill-based fork of multiprocessing called 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()