1

I had a problem for multiprocess, and below it is the code that I used to perform a test:

import multiprocessing


class Test():
    def __init__(self):
        pass

    def add(self,x,y):
        self.x = x
        self.y = y
        return self.x + self.y


class Worker(Test):
    def do_me(self,x,y):
        return self.add(x,y)


if __name__ == '__main__':

    job = Worker()

    # #single process
    # x = 1
    # y = 9
    # result = job.do_me(x,y)
    # print "%2d +%2d = %2d "%(x,y,result)

    #multiprocess
    x = [1,2,3]
    y = [9,7,5]

    pool = multiprocessing.Pool(processes=4)
    retults = [ pool.map(job.do_me, ((x[i], y[i]),)) for i in range(len(x)) ]
    print results

For single process, it will work fine. However, for multiprocess, it did not. The error msg is:

cPickle.PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemet hod failed

I searched here, but i did not quite understand the machanism. Could someone give me more help? Cheers.

1
  • Your "here" link is nonexistent. Where did you search? Commented Dec 28, 2014 at 20:24

1 Answer 1

2

As the error suggests, you can't pickle instance methods. The problem is this line:

pool.map(job.do_me, ((x[i], y[i]),)) for i in range(len(x))

The mechanism behind this is that when the map function sends the function (the first argument) to all of the workers, it has to serialize it to data somehow, so it's using a mechanism called pickling. There are other mechanisms, this is the a very common one in Python).

When it's trying to pickle an instance method (specifically method do_me, of instances of type Worker) and send it to the pool (for the workers to know what method they're supposed to execute), it fails. Because you can't pickle instance methods.

You can fix this by moving the method to the module level (removing the Worker class):

def do_me(test_instance):
    return test_instance.add(x,y)

Now we don't have access to self, since we're using the test_instance that's sent here explicitly, so this method isn't bound to the Test class anymore... Or put in other words - this isn't an instance method anymore. Now make sure you re-factor everything to work as you plan.

The Test class should have something along this structure to keep the list comprehension in the argument construction to pool.map simple:

class Test():
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def add(self,x,y):
        return self.x + self.y

Adn then calling it like this:

results = pool.map(do_me, [Test(x[i], y[i]) for i in range(len(x))])

Full code:

import multiprocessing


class Test():
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def add(self):
        return self.x + self.y


def do_me(test_instance):

    return test_instance.add()


if __name__ == '__main__':

    x = [1,2,3]
    y = [9,7,5]

    pool = multiprocessing.Pool(processes=4)
    results = pool.map(do_me, [Test(x[i], y[i]) for i in range(len(x))])
    print results

Some notes:

  1. pool.map already returns a list

  2. __init__ is the standard place to initialize the object data (x, y in your case).

  3. The function pool.map is using is applied to each item of the iterable, so it should be a single-argument function (you can use a tuple, but you have to unpack it).

Sign up to request clarification or add additional context in comments.

10 Comments

I added a bit more details, but if you'll be more specific I'll be more specific :)
@ReutSharabani , you also need a specific argument for self in the pool.map call -- you can't just have two args once you've made do_me a function rather than a method! That first arg had better be an instance of Test, BTW:-)
@AlexMartelli could happen to us all!
what I can see is, you missed job. in pool.map call. I did not understand this. Also, if not using map, what other machanism or methods I can use?
While it's perfectly reasonable you can do what you want with an instance method, it doesn't work out-of-the-box. You have to manually implement the pickling and unpickling process. Read here: bytes.com/topic/python/answers/…
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.