multiprocessing and remote objects

Frank Millman frank at chagford.com
Fri Jan 8 10:33:42 CET 2010


Hi all

I am experimenting with the multiprocessing module, to get a feel of what is 
possible and what is not. I have got a situation that does not behave as 
expected. I can work around it, but I would like to find out the underlying 
reason, to get a more solid understanding.

I am trying to create 'remote objects' that can be shared between processes. 
I can create and return an instance of a class, with no problem. Now I want 
to add a method to the class which, when called remotely, creates and 
returns an instance of another class. I cannot get this to work.

On the server side I have -

    tables = {}  # a cache of table instances, keyed on name

    class Table(object):
        def __init__(self, name):
            self.name = name

    def get_table(self, tablename):
        # if table with this name does not exist,
        #   create it and store it in cache
        if tablename not in tables:
            tables[tablename] = Table(tablename)
        # retrieve table instance from cache and return it
        return tables[tablename]

    class MyManager(BaseManager): pass

    MyManager.register('get_table', get_table,
        method_to_typeid={'get_table': 'Table')
    MyManager.register('Table', Table)

    if __name__ == '__main__':
        manager = MyManager(address=('127.0.0.1', 50000))
        server = manager.get_server()
        server.serve_forever()

On the client side I have -

    class MyManager(BaseManager): pass

    MyManager.register('get_table')
    MyManager.register('Table')

    if __name__ == '__main__':
        manager = MyManager(address=('127.0.0.1', 50000))
        manager.connect()

        cust = manager.get_table('Customers')

So far so good.

Then I extend the server program as follows -

    class Table(object):
        def __init__(self, name):
            self.name = name
+           self.columns = {}

+       def add_column(self, colname):
+           if colname not in self.columns:
+               self.columns[colname] = Column(colname)
+           return self.columns[colname]

+   class Column(object):
+       def __init__(self, colname):
+           self.colname = colname

    MyManager.register('get_table', get_table,
        method_to_typeid={'get_table': 'Table')
-   MyManager.register('Table', Table)
+   MyManager.register('Table', Table,
+       method_to_typeid={'add_column': 'Column')
+   MyManager.register('Column', Column)

and I extend the client program as follows -

    MyManager.register('get_table')
    MyManager.register('Table')
+   MyManager.register('Column')

        cust = manager.get_table('Customers')
+       acno = cust.add_column('Acno')

The server appears to create and return the column ok, but on the client 
side I get the following traceback -

    Traceback (most recent call last):
      File "F:\junk\multiprocess\mp13b.py", line 29, in <module>
        acno = cust.add_column('Acno')
      File "<string>", line 2, in add_column
      File "C:\Python26\lib\multiprocessing\managers.py", line 726, in 
_callmethod
        kind, result = conn.recv()
    AttributeError: 'module' object has no attribute 'Column'

Does anyone know if it is possible to do what I am attempting, and what the 
correct approach is?

BTW, version is Python 2.6.2.

Thanks

Frank Millman






More information about the Python-list mailing list