我正在尝试编写一个应用程序,该应用程序将函数与multiprocessing.Pool
同时应用。我希望这个函数是一个实例方法(所以我可以在不同的子类中定义它)。这似乎是不可能的;正如我在别处学到的,显然bound methods can't be pickled。那么,为什么以绑定方法作为目标启动multiprocessing.Process
?以下代码:
import multiprocessing
def test1():
print "Hello, world 1"
def increment(x):
return x + 1
class testClass():
def process(self):
process1 = multiprocessing.Process(target=test1)
process1.start()
process1.join()
process2 = multiprocessing.Process(target=self.test2)
process2.start()
process2.join()
def pool(self):
pool = multiprocessing.Pool(1)
for answer in pool.imap(increment, range(10)):
print answer
print
for answer in pool.imap(self.square, range(10)):
print answer
def test2(self):
print "Hello, world 2"
def square(self, x):
return x * x
def main():
c = testClass()
c.process()
c.pool()
if __name__ == "__main__":
main()
生成此输出:
Hello, world 1
Hello, world 2
1
2
3
4
5
6
7
8
9
10
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Python27\Lib\threading.py", line 551, in __bootstrap_inner
self.run()
File "C:\Python27\Lib\threading.py", line 504, in run
self.__target(*self.__args, **self.__kwargs)
File "C:\Python27\Lib\multiprocessing\pool.py", line 319, in _handle_tasks
put(task)
PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed
为什么进程可以处理绑定的方法,而不能处理池?
这里有一个我有时使用的替代方法,它在Python2.x中有效:
您可以创建一个顶级的“别名”,按实例方法排序,该别名接受要在池中运行其实例方法的对象,并让该对象为您调用实例方法:
此代码生成此输出:
一个限制是,不能将其用于修改对象的方法。每个进程都会获得它正在调用其方法的对象的副本,因此更改不会传播回主进程。如果不需要从调用的方法修改对象,这可能是一个简单的解决方案。
pickle
模块通常无法pickle实例方法:但是,} that adds some code to enable this feature :
multiprocessing
模块has a custom ^{您可以使用^{} 模块复制它,以查看它是否适合您自己:
使用} :
Process.start
在Windows上生成新进程时,it pickles all the parameters you passed to the child process using this custom ^{注意“发送信息给孩子”部分。它使用
dump
函数,它使用ForkingPickler
来pickle数据,这意味着您的实例方法可以被pickle。现在,当您使用} directly 中实现的,因此它不利用
multiprocessing.Pool
上的方法向子进程发送方法时,它使用multiprocessing.Pipe
来pickle数据。在Python 2.7中,multiprocessing.Pipe
是在C,and calls ^{ForkingPickler
。这意味着pickling实例方法不起作用。但是,如果使用
copy_reg
来注册instancemethod
类型,而不是自定义的Pickler
,所有酸洗尝试都将受到影响。因此,您可以使用它来启用pickling实例方法,甚至可以通过Pool
:输出:
还要注意,在Python 3.x中,
pickle
可以本机pickle实例方法类型,因此这些都不再重要。:)在Python 2中有一种更简单的工作方式,就是包装原始的实例方法。在MacOSX和Linux上运行良好,而在Windows上运行不好,测试了Python2.7
相关问题 更多 >
编程相关推荐