Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python multiprocessing : AttributeError: Can't pickle local object

Tags:

python

I have a method inside a class to return a func which parameters may change.

The Interface function accept two parameters, f and its args.I want to use mp.pool to accelerate it.However, it returns an error.

from multiprocessing import Pool
# from multiprocess import Pool
# from pathos.multiprocessing import ProcessingPool as Pool
import pickle
import dill


class Temp:
    def __init__(self, a):
        self.a = a

    def test(self):
        def test1(x):
            return self.a + x

        return test1


def InterfaceFunc(f, x):
    mypool = Pool(4)
    return list(mypool.map(f, x))


if __name__ == "__main__":
    t1 = Temp(1).test()
    x = [1, 2, 3, 1, 2]

    res1 = list(map(t1, x))
    print(res1)

    res2 = InterfaceFunc(t1, x)

it raise the same error:

AttributeError: Can't pickle local object 'Temp.test.<locals>.test1'

I have tried 3 method:

What can multiprocessing and dill do together?

Replace pickle in Python multiprocessing lib

Python Multiprocessing Pool Map: AttributeError: Can't pickle local object

Method 1, 2 :

 from multiprocess import Pool
 from pathos.multiprocessing import ProcessingPool as Pool

It raise error:

 File "E:\Users\ll\Anaconda3\lib\site-packages\dill\_dill.py", line 577, in _load_type
    return _reverse_typemap[name]
KeyError: 'ClassType'

Method3 needs to change the code , however I cant simply move the func out of the class because I need f to be a parameter for the Interface.

Do you have any suggestions? I'm an inexperienced newcomer.

like image 973
abcyunice Avatar asked Jun 04 '20 03:06

abcyunice


1 Answers

Python can't pickle the closure, but all you really need is something that you can call that retains state. The __call__ method makes a class instance callable, so use that

from multiprocessing import Pool

class TempTest1:

    def __init__(self, a):
        self.a = a

    def __call__(self, x):
        return self.a + x

class Temp:
    def __init__(self, a):
        self.a = a

    def test(self):
        return TempTest1(self.a)

def InterfaceFunc(f, x):
    mypool = Pool(4)
    return list(mypool.map(f, x))

if __name__ == "__main__":
    t1 = Temp(1).test()
    x = [1, 2, 3, 1, 2]

    res1 = list(map(t1, x))
    print(res1)

    res2 = InterfaceFunc(t1, x)
    print(res2)
like image 167
tdelaney Avatar answered Nov 06 '22 07:11

tdelaney