Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Can';t pickle静态方法-多处理-Python_Python_Class_Multiprocessing_Pickle_Pool - Fatal编程技术网

Can';t pickle静态方法-多处理-Python

Can';t pickle静态方法-多处理-Python,python,class,multiprocessing,pickle,pool,Python,Class,Multiprocessing,Pickle,Pool,我正在对我的代码应用一些并行化,在其中我使用类。我知道如果没有Python提供的任何其他方法,就不可能选择一个类方法。我找到了解决办法。在我的代码中,我必须使用类来定义应该并行化的部分。在这里,我发布了一个非常简单的代码,只代表我的结构(是一样的,但我删除了方法的内容,这是大量的数学演算,对我得到的输出无关紧要)。问题是因为我可以pickle一种方法(shepard_插值),但用另一种方法(计算方向不确定性),我得到了pickle误差。我不知道为什么会发生这种情况,也不知道为什么会部分起作用 d

我正在对我的代码应用一些并行化,在其中我使用类。我知道如果没有Python提供的任何其他方法,就不可能选择一个类方法。我找到了解决办法。在我的代码中,我必须使用类来定义应该并行化的部分。在这里,我发布了一个非常简单的代码,只代表我的结构(是一样的,但我删除了方法的内容,这是大量的数学演算,对我得到的输出无关紧要)。问题是因为我可以pickle一种方法(shepard_插值),但用另一种方法(计算方向不确定性),我得到了pickle误差。我不知道为什么会发生这种情况,也不知道为什么会部分起作用

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 lookupbuiltin。函数失败”。这几乎是相同的发现。我看到的唯一区别是我的方法是静态的

编辑:

我注意到,在我的calculate\u orientation\u不确定性中,当我将函数调用为
result=pool.apply\u async(VariabilityOfGradients.aux())
,也就是说,使用括号(在文档示例中我从未看到过),它似乎可以工作。但是,当我试图得到结果时,我收到“TypeError:'int'对象不可调用”


任何帮助都将不胜感激。提前感谢。

您可以在模块级别定义普通函数,也可以定义静态方法。这保留了staticmethod的调用语法、内省和可继承性特性,同时避免了pickle问题:

def aux():
    return "VoG - Sucess" 

class VariabilityOfGradients(object):
    aux = staticmethod(aux)

比如说,

import copy_reg
import types
from itertools import product
import multiprocessing as mp

def _pickle_method(method):
    """
    Author: Steven Bethard (author of argparse)
    http://bytes.com/topic/python/answers/552476-why-cant-you-pickle-instancemethods
    """
    func_name = method.im_func.__name__
    obj = method.im_self
    cls = method.im_class
    cls_name = ''
    if func_name.startswith('__') and not func_name.endswith('__'):
        cls_name = cls.__name__.lstrip('_')
    if cls_name:
        func_name = '_' + cls_name + func_name
    return _unpickle_method, (func_name, obj, cls)


def _unpickle_method(func_name, obj, cls):
    """
    Author: Steven Bethard
    http://bytes.com/topic/python/answers/552476-why-cant-you-pickle-instancemethods
    """
    for cls in cls.mro():
        try:
            func = cls.__dict__[func_name]
        except KeyError:
            pass
        else:
            break
    return func.__get__(obj, cls)

copy_reg.pickle(types.MethodType, _pickle_method, _unpickle_method)

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 - Success"       

def aux():
    return "VoG - Sucess" 

class VariabilityOfGradients(object):
    aux = staticmethod(aux)

    @staticmethod
    def calculate_orientation_uncertainty():
        pool = mp.Pool()
        results = []
        for x, y in product(range(1, 5), range(1, 5)):
            # result = pool.apply_async(aux) # this works too
            result = pool.apply_async(VariabilityOfGradients.aux, callback=results.append)
        pool.close()
        pool.join()
        print(results)


if __name__ == '__main__':  
    results = []
    pool = mp.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()   
屈服

ImD - Success
ImD - Success
ImD - Success
['VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess', 'VoG - Sucess']

顺便说一下,在
池.apply_async
(例如
ImageData.shepard_interpolation
)调用的函数完成之前,会阻止调用过程。所以

for _ in range(3):
    result = pool.apply_async(ImageData.shepard_interpolation, args=[ImageData()])
    results.append(result.get())
实际上是按顺序调用
ImageData.shepard_interpolation
,这违背了池的目的

相反,你可以使用

for _ in range(3):
    pool.apply_async(ImageData.shepard_interpolation, args=[ImageData()],
                     callback=results.append)
回调函数(例如,
results.append
)在函数完成时在调用过程的线程中调用。它被发送一个参数——函数的返回值。因此,没有任何东西会阻止这三个
池。apply_async
调用的快速进行,对
ImageData.shepard_interpolation
的三个调用所做的工作将同时执行

或者,在这里使用
pool.map
可能更简单

results = pool.map(ImageData.shepard_interpolation, [ImageData()]*3)

如果使用名为
pathos.multiprocessing
多处理
分支,则可以在多处理的
映射
函数中直接使用类和类方法。这是因为使用了
dill
而不是
pickle
cPickle
,并且
dill
几乎可以序列化python中的任何内容

pathos.multi-processing
还提供了一个异步映射函数…它可以
map
具有多个参数的函数(例如
map(math.pow,[1,2,3],[4,5,6])

见:

以及:

在此处获取代码:


pathos
也有一个异步映射(
amap
),以及
imap

我不确定这是否是您想要的,但我的使用略有不同。我想使用同一个类中运行在多个线程上的类的方法

我就是这样实现的:

from multiprocessing import Pool

class Product(object):

        def __init__(self):
                self.logger = "test"

        def f(self, x):
                print(self.logger)
                return x*x

        def multi(self):
                p = Pool(5)
                print(p.starmap(Product.f, [(Product(), 1), (Product(), 2), (Product(), 3)]))


if __name__ == '__main__':
        obj = Product()
        obj.multi()

如果这不是您的代码,人们很可能会要求您发布您遇到问题的确切代码。只是一个通知。另外,您使用的是哪一个Python版本,pickle在版本中的行为有点不同,我个人认为,只要类对象不包含套接字或活动线程之类的实例,pickle就不会有问题。通常,您将一个线程化类存储在两个类对象中,一个可能继承另一个,或者只是在线程化类中初始化一个类,如果有意义的话,只在“内部”类中线程化。这是我的代码。我只是删除了方法中的内容(对问题来说无关紧要,大量的数学运算是不必要的)。错误消息是什么?@pceccon:关于编辑:如果使用
pool.apply_async(variabilityofgradens.aux())
那么首先调用
variabilityofgradens.aux()
,然后将其返回值发送到
池。应用\u async
。这不是您想要的,因为池工作程序没有同时调用
VariabilityOfGradients.aux
。关于原始问题:
isinstance(func,types.MethodType)
False
func
是静态方法时,所以
copy\u reg.pickle(types.MethodType,\u pickle\u method,\u unpickle\u method)
不影响静态方法。简单的解决方法是在全局模块级别将staticmethod设置为普通函数。我知道这一点,但我只是想知道是否有一种方法可以在Python中实现我想要的功能,而不是使用这种方法。但似乎我不能。你好,@unutbu。我能再问你一件事吗?它工作了,但是,正如您所看到的,在这个示例中,我迭代了25次。在我的问题中,我有两个200 x 200的for,我的aux函数有很多数学处理。正在发生的事情是,调用这个并行化程序要比根本不使用多处理程序花费更多的时间。你知道为什么吗?我在本例中应用的概念正确吗?谢谢。你能把有问题的代码发出去吗?可运行的代码会有很大帮助。
from multiprocessing import Pool

class Product(object):

        def __init__(self):
                self.logger = "test"

        def f(self, x):
                print(self.logger)
                return x*x

        def multi(self):
                p = Pool(5)
                print(p.starmap(Product.f, [(Product(), 1), (Product(), 2), (Product(), 3)]))


if __name__ == '__main__':
        obj = Product()
        obj.multi()