Skip to content Skip to sidebar Skip to footer

Handling The Classmethod Pickling Issue With Copy_reg

I met a pickling error when dealing with multiprocessing: from multiprocessing import Pool def test_func(x): return x**2 class Test: @classmethod def func(cls,

Solution 1:

I modified the recipe to make it work with classmethod. Here's the code.

import copy_reg
import types

def_pickle_method(method):
    func_name = method.im_func.__name__
    obj = method.im_self
    cls = method.im_classif func_name.startswith('__') andnot func_name.endswith('__'):
        #deal with mangled names
        cls_name = cls.__name__.lstrip('_')
        func_name = '_%s%s' % (cls_name, func_name)
    return _unpickle_method, (func_name, obj, cls)

def_unpickle_method(func_name, obj, cls):
    if obj and func_name in obj.__dict__:
        cls, obj = obj, None# if func_name is classmethodfor cls in cls.__mro__:
        try:
            func = cls.__dict__[func_name]
        except KeyError:
            passelse:
            breakreturn func.__get__(obj, cls)

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

Solution 2:

The following solution now also handles class methods correctly. Please let me know if there is still something missing.

def_pickle_method(method):
    """
    Pickle methods properly, including class methods.
    """
    func_name = method.im_func.__name__
    obj = method.im_self
    cls = method.im_classifisinstance(cls, type):
        # handle classmethods differently
        cls = obj
        obj = Noneif func_name.startswith('__') andnot func_name.endswith('__'):
        #deal with mangled names
        cls_name = cls.__name__.lstrip('_')
        func_name = '_%s%s' % (cls_name, func_name)

    return _unpickle_method, (func_name, obj, cls)

def_unpickle_method(func_name, obj, cls):
    """
    Unpickle methods properly, including class methods.
    """if obj isNone:
        return cls.__dict__[func_name].__get__(obj, cls)
    for cls in cls.__mro__:
        try:
            func = cls.__dict__[func_name]
        except KeyError:
            passelse:
            breakreturn func.__get__(obj, cls)

Solution 3:

Instead of returning the actual class object from _pickle_method, return a string that can be used to import it when unpickling and then do that in _unpickle_method

Post a Comment for "Handling The Classmethod Pickling Issue With Copy_reg"