我最初的问题是我正在尝试执行以下操作:
def submit_decoder_process(decoder, input_line):
decoder.process_line(input_line)
return decoder
self.pool = Pool(processes=num_of_processes)
self.pool.apply_async(submit_decoder_process, [decoder, input_line]).get()
解码器在这里有点介绍,但重要的是解码器是一个用调用setParseAction()的PyParsing表达式初始化的对象。这使多处理使用的pickle失败,这反过来又失败了上述代码。
现在,这是我已经隔离和简化的pickle / PyParsing问题。 由于pickle失败,以下代码会产生错误消息。
import pickle
from pyparsing import *
def my_pa_func():
pass
pickle.dumps(Word(nums).setParseAction(my_pa_func))
错误讯息:
pickle.PicklingError: Can't pickle <function wrapper at 0x00000000026534A8>: it's not found as pyparsing.wrapper
现在如果删除调用.setParseAction(my_pa_func),它将没有问题:
pickle.dumps(Word(nums))
我怎样才能解决这个问题?多处理使用泡菜,所以我猜不到它。据说使用dill的pathos包不够成熟,至少,我在Windows-64bit上安装它时遇到问题。我真的在这里摸不着头脑。
答案 0 :(得分:5)
好的,这是受Rocksportrocker启发的解决方案:Python multiprocessing pickling error
我们的想法是在不同过程之间来回传递不能被腌制的物体,然后再过去&#34; undill&#34;它通过后:
from multiprocessing import Pool
import dill
def submit_decoder_process(decoder_dill, input_line):
decoder = dill.loads(decoder_dill) # undill after it was passed to a pool process
decoder.process_line(input_line)
return dill.dumps(decoder) # dill before passing back to parent process
self.pool = Pool(processes=num_of_processes)
# Dill before sending to a pool process
decoder_processed = dill.loads(self.pool.apply_async(submit_decoder_process, [dill.dumps(decoder), input_line]).get())
答案 1 :(得分:0)
https://docs.python.org/2/library/pickle.html#what-can-be-pickled-and-unpickled
multiprocessing.Pool使用Pickle协议来序列化函数和模块名称(在您的示例中为setParseAction和pyparse),这些名称通过Pipe传递给子进程。
子进程一旦收到它们,就会导入模块并尝试调用该函数。问题是你传递的不是函数而是方法。要解决它,Pickle协议应该足够聪明,可以使用'user'参数构建'Word'对象,然后调用setParseAction方法。由于处理这些情况过于复杂,因此Pickle协议会阻止您序列化非顶级函数。
要解决您的问题,您可以指示Pickle的模块如何序列化setParseAction方法(https://docs.python.org/2/library/pickle.html#pickle-protocol),或者以传递给Pool.apply_async的方式可序列化的方式重构代码。
如果将Word对象传递给子进程并让它调用Word(),该怎么办?setParseAction()?
答案 2 :(得分:0)
我建议pathos.multiprocessing
,如你所说。当然,我是pathos
作者,所以我想这并不奇怪。您可能会遇到distutils
错误,如下所示:https://github.com/uqfoundation/pathos/issues/49。
使用dill
的解决方案是一个很好的解决方法。您也可以放弃安装整个pathos
软件包,只需安装pathos
软件包的multiprocessing
分叉(使用dill
代替pickle
)。您可以在此处找到它:http://dev.danse.us/packages或此处:https://github.com/uqfoundation/pathos/tree/master/external,