[英]Why do I get different results when using multiprocessing with an instance method vs with a function?
For the following code, which passes an instance method to the Pool
, the list is empty at the end of the script: 对于将实例方法传递给
Pool
的以下代码,该脚本末尾的列表为空:
import time
from multiprocessing import Pool
class Hello:
def __init__(self):
self.result_list=[]
def f(self,x,y):
time.sleep(2)
return x*y
def log_result(self,result):
# This is called whenever foo_pool(i) returns a result.
# result_list is modified only by the main process, not the pool workers.
print result
self.result_list.append(result)
if __name__ == '__main__':
pool = Pool() # start 4 worker processes
h=Hello()
for i in range(10):
pool.apply_async(h.f, args = (i,i, ), callback = h.log_result)
pool.close()
pool.join()
print(h.result_list)
With this code, the list is populated as expected. 使用此代码,列表将按预期填充。
import multiprocessing as mp
import time
def foo_pool(x):
time.sleep(2)
return x*x
result_list = []
def log_result(result):
# This is called whenever foo_pool(i) returns a result.
# result_list is modified only by the main process, not the pool workers.
result_list.append(result)
def apply_async_with_callback():
pool = mp.Pool()
for i in range(10):
pool.apply_async(foo_pool, args = (i, ), callback = log_result)
pool.close()
pool.join()
print(result_list)
if __name__ == '__main__':
apply_async_with_callback()
What's different about the two? 两者有什么不同? Why doesn't it work with the instance method?
为什么它不适用于实例方法?
If you actually try to fetch the result of one of you apply_async
calls, you'll see that they're all failing with this error: 如果您实际上尝试获取其中一个
apply_async
调用的结果,您将看到它们都失败并出现此错误:
cPickle.PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed
This is because in Python 2.x, instance methods aren't picklable by default, so trying to pass the instance method hf
to the worker process fails. 这是因为在Python 2.x中,默认情况下实例方法不可选,因此尝试将实例方法
hf
传递给工作进程失败。 This is actually fixed in Python 3, but you can backport the behavior to Python 2 quite easily, using the copy_reg
module: 这实际上已在Python 3中修复,但您可以使用
copy_reg
模块将行为很容易地copy_reg
移植到Python 2:
import time
from multiprocessing import Pool
import copy_reg
import types
def _reduce_method(m):
if m.__self__ is None:
return getattr, (m.__class__, m.__func__.__name__)
else:
return getattr, (m.__self__, m.__func__.__name__)
copy_reg.pickle(types.MethodType, _reduce_method)
class Hello:
def __init__(self):
self.result_list=[]
def f(self,x,y):
time.sleep(2)
return x*y
def log_result(self, result):
print(result)
self.result_list.append(result)
if __name__ == '__main__':
pool = Pool()
h = Hello()
for i in range(10):
pool.apply_async(h.f, args = (i,i), callback=h.log_result)
pool.close()
pool.join()
print(h.result_list)
Output: 输出:
0
4
49
25
1
16
36
9
64
81
[0, 4, 49, 25, 1, 16, 36, 9, 64, 81]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.