【发布时间】:2014-01-14 10:25:06
【问题描述】:
我正在对我使用类的代码应用一些并行化。我知道如果没有与 Python 提供的任何其他方法不同,就不可能选择一个类方法。我找到了解决方案here。在我的代码中,我必须使用类进行并行化的部分。在这里,我发布了一个非常简单的代码,仅代表我的结构(相同,但我删除了方法内容,这是很多数学演算,对我得到的输出来说微不足道)。问题是因为我可以腌制一种方法(shepard_interpolation),但使用另一种方法(calculate_orientation_uncertainty)我得到了腌制错误。我不知道为什么会这样,或者为什么会部分起作用。
def _pickle_method(method):
func_name = method.im_func.__name__
obj = method.im_self
cls = method.im_class
if func_name.startswith('__') and not func_name.endswith('__'): #deal with mangled names
cls_name = cls.__name__.lstrip('_')
func_name = '_' + cls_name + func_name
print cls
return _unpickle_method, (func_name, obj, cls)
def _unpickle_method(func_name, obj, cls):
for cls in cls.__mro__:
try:
func = cls.__dict__[func_name]
except KeyError:
pass
else:
break
return func.__get__(obj, cls)
class ImageData(object):
def __init__(self, width=60, height=60):
self.width = width
self.height = height
self.data = []
for i in range(width):
self.data.append([0] * height)
def shepard_interpolation(self, seeds=20):
print "ImD - Sucess"
import copy_reg
import types
from itertools import product
from multiprocessing import Pool
copy_reg.pickle(types.MethodType, _pickle_method, _unpickle_method)
class VariabilityOfGradients(object):
def __init__(self):
pass
@staticmethod
def aux():
return "VoG - Sucess"
@staticmethod
def calculate_orientation_uncertainty():
results = []
pool = Pool()
for x, y in product(range(1, 5), range(1, 5)):
result = pool.apply_async(VariabilityOfGradients.aux)
results.append(result.get())
pool.close()
pool.join()
if __name__ == '__main__':
results = []
pool = Pool()
for _ in range(3):
result = pool.apply_async(ImageData.shepard_interpolation, args=[ImageData()])
results.append(result.get())
pool.close()
pool.join()
VariabilityOfGradients.calculate_orientation_uncertainty()
运行时,出现“PicklingError: Can't pickle : attribute lookup builtin.function failed”。这与here 几乎相同。我看到的唯一区别是我的方法是静态的。
编辑:
我注意到,在我的 calculate_orientation_uncertainty 中,当我将函数调用为 result = pool.apply_async(VariabilityOfGradients.aux()) 时,即使用括号(在文档示例中我从未见过这个),它似乎有效。但是,当我尝试获取结果时,我收到“TypeError: 'int' object is not callable”...
任何帮助将不胜感激。提前谢谢你。
【问题讨论】:
-
如果这不是您的代码,人们很可能会要求您发布您遇到问题的确切代码。只是一个通知。另外,您使用的是哪个 Python 版本,pickle 在版本中的行为有点不同,而且我对一个类对象进行酸洗没有问题,只要它不包含诸如套接字或活动线程之类的实例.通常你将一个线程类存储在两个类对象中,一个可能继承另一个类,或者只是在线程类中启动一个类,如果有意义的话,只需线程化“内部”类。
-
这是我的代码。我只是删除了方法中的内容(对于问题来说无关紧要,很多数学演算是不必要的)。
-
错误信息是什么?
-
@pceccon:关于您的编辑:如果您使用
pool.apply_async(VariabilityOfGradients.aux()),那么您首先调用VariabilityOfGradients.aux(),然后将其返回值发送到pool.apply_async。这不是您想要的,因为池工作人员没有同时调用VariabilityOfGradients.aux。 -
关于原问题:
isinstance(func, types.MethodType)是False当func是一个静态方法,所以copy_reg.pickle(types.MethodType, _pickle_method, _unpickle_method)不影响静态方法。简单的解决方法是在全局模块级别使您的静态方法成为普通函数。
标签: python class multiprocessing pickle pool