4

How do I create the python shared object of my class which can be modified by worker processes. I created the worker processes by using multiprocessing.Process module. I have some knowledge about multiprocessing.Manager module. Can any one explain with example how to register my class in to Manager, start the manager and create the shared object of my class.

Rahul.Shikhare
  • 179
  • 1
  • 16

1 Answers1

6

Here is an example:

from multiprocessing import Process, Pool
from multiprocessing.managers import BaseManager


class MySharedClass(object):
    stored_value = 0
    def get(self):
        return self.stored_value

    def set(self, new_value):
        self.stored_value = new_value
        return self.stored_value


class MyManager(BaseManager):
    pass


MyManager.register('MySharedClass', MySharedClass)

def worker ( proxy_object, i):
    proxy_object.set( proxy_object.get() + i )
    print ("id %d, sum %d" %(i, proxy_object.get()))
    return proxy_object


if __name__ == '__main__':
    manager = MyManager()
    manager.start()
    shared = manager.MySharedClass()

    pool = Pool(5)
    for i in range(33):
        pool.apply(func=worker, args=(shared, i))
    pool.close()
    pool.join()
    print "result: %d" % shared.get()

id 0, sum 0
id 1, sum 1
id 2, sum 3
...
id 31, sum 496
id 32, sum 528
result: 528

Another variant (have never use it in the real project):

from multiprocessing import Process, Pool
from multiprocessing.managers import BaseManager, NamespaceProxy


class MySharedClass(object):
    def __init__(self):
        self.stored_value = 0

    def get(self):
        return self.stored_value

    def set(self, new_value):
        self.stored_value = new_value
        return self.stored_value


class MyManager(BaseManager):
    pass

class MyProxy(NamespaceProxy):
    _exposed_ = ('__getattribute__', '__setattr__', '__delattr__')# add 'get' to use get


    #def get(self):
    #    callmethod = object.__getattribute__(self, '_callmethod')
    #    return callmethod('get')

MyManager.register('MySharedClass', MySharedClass, MyProxy)

def worker ( proxy_object, i):
    proxy_object.stored_value =  proxy_object.stored_value + i
    print ("id %d, sum %d" %(i, proxy_object.stored_value))
    return proxy_object


if __name__ == '__main__':
    manager = MyManager()
    manager.start()
    shared = manager.MySharedClass()
    print shared.stored_value

    pool = Pool(5)
    for i in range(33):
        pool.apply(func=worker, args=(shared, i))
    pool.close()
    pool.join()
    print "result: %d" % shared.stored_value
minskster
  • 512
  • 3
  • 6
  • 1
    if I put def __init__(self) method and put self.stored_value = 0 in it and trying to access this variable like proxy_object.stored_value += 1. Why It is giving the Error : AttributeError: 'AutoProxy[MySharedClass]' object has no attribute 'stored_value'. My point is if I create a same variable using multiprocessing Value() or Manager() class and share it; then we can access using object reference operator (.) . I want to access the object variables of MySharedClass() in worker process using object reference operator – Rahul.Shikhare Mar 01 '16 at 11:40
  • It would be nice to use @property and <>.setter decorators. But I have found only one way and have never use it before. It's NamespaceProxy. Don't know what kind of issues can be appeared. Look at the updated answer. – minskster Mar 01 '16 at 13:53
  • In the above solution if I am importing ' import eventlet' and calling 'eventlet.monkey_patch() ' It is giving the Error as : IOError: [Errno 11] Resource temporarily unavailable – Rahul.Shikhare Mar 02 '16 at 12:17
  • I have never used eventlet, will try as get a time, but I have an application with multiprocessing, gevent ( another concurrent networking library), flask and websocket. It was a problem to get it all workable together. I spent a lot of time to find compatible versions of all packages gevent, gevent-socketio, greenlet ... . – minskster Mar 03 '16 at 07:05