[issue20854] multiprocessing.managers.Server: problem with returning proxy of registered object
Allis Tauri
report at bugs.python.org
Sun Mar 9 10:24:15 CET 2014
Allis Tauri added the comment:
Thanks for the suggestion.
method_to_typeid and create_method are documented features, so I don't see why not. It does the trick in a cleaner way than my workaround: a metaclass for MyClass that just checks the arguments before creating a new instance. It just seems to me somewhat counterintuitive.
Another issue that arises in my case is: when I try to pass a proxy of MyClass to a subprocess it looses its' _manager during pickling and thus the ability to create proxies for children returned by get_child. This is solved by reimplementing the (not-working: http://bugs.python.org/issue5862) __reduce__ method of BaseManager in MyManager and creating corresponding custom proxy for MyClass with __reduce__ method also reimplemented.
So the working solution for the situation is:
either
1.1)
class ReturnProxy(type):
def __call__(cls, *args, **kwargs):
if not kwargs and args and isinstance(args[0], cls):
return args[0]
return super(ReturnProxy, cls).__call__(*args, **kwargs)
class MyClass(object):
__metaclass__ = ReturnProxy
###class body###
or
1.2)
Your solution with the second typeid registration.
2)
class AutoProxyMeta(type):
'''Metaclass that replicates multiprocessing.managers.MakeProxyType
functionality, but allows proxy classes that use it to be pickable'''
def __new__(cls, name, bases, attrs):
dic = {}
for meth in attrs.get('_exposed_', ()):
exec '''def %s(self, *args, **kwds):
return self._callmethod(%r, args, kwds)''' % (meth, meth) in dic
dic.update(attrs)
return super(AutoProxyMeta, cls).__new__(cls, name, bases, dic)
class MyClassProxy(BaseProxy):
__metaclass__ = AutoProxyMeta
_exposed_ = ('get_child',)
_method_to_typeid_ = dict(get_child='MyClass')
#or: _method_to_typeid_ = dict(get_child='_MyClass')
def __reduce__(self):
_unpickle, (cls, token, serializer, kwds) = BaseProxy.__reduce__(self)
kwds['manager'] = self._manager
return _unpickle, (cls, token, serializer, kwds)
class MyClassManager(UManager):
def __reduce__(self):
return (RebuildMyClassManager,
(self._address, None, self._serializer))
WorkCounterManager.register('MyClass', MyClass, MyClassProxy)
#optionally: WorkCounterManager.register('_MyClass', None, MyClassProxy, create_method=False)
def RebuildMyClassManager(address, authkey, serializer):
mgr = MyClassManager(address, authkey, serializer)
mgr.connect()
return mgr
----------
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue20854>
_______________________________________
More information about the Python-bugs-list
mailing list