Python: Cómo pasar un objeto Autoproxy

Necesito pasar el proxy de un objeto a otro objeto, pero cada vez que hago esto, el otro objeto es el referente del proxy y no el proxy en sí. Esto es algo similar a lo que estoy tratando de hacer:

import multiprocessing.managers as m class Foo(object): def __init__(self): self.manager = MyManager() self.manager.register('Bar', Bar) self.manager.start() self.bar = self.manager.Bar() self.bar.set_proxy(self.bar) class Bar(object): def __init__(self): self.proxy = None def set_proxy(self, proxy): self.proxy = proxy class MyManager(m.BaseManager): pass test = Foo() 

siempre que hago esto, el valor en self.proxy es la instancia de Foo que creé y no el proxy que devolvió el administrador.

Esto se debe a una falla de diseño, o quizás a un error , en la forma en que las instancias de Proxy se eliminan. En este momento, si el código de descifrado ve que se está ejecutando dentro de un Manager , le da el referente cuando deselecciona, en lugar del Proxy :

 def RebuildProxy(func, token, serializer, kwds): ''' Function used for unpickling proxy objects. If possible the shared object is returned, or otherwise a proxy for it. ''' server = getattr(process.current_process(), '_manager_server', None) if server and server.address == token.address: return server.id_to_obj[token.id][0] # This returns the referent else: incref = ( kwds.pop('incref', True) and not getattr(process.current_process(), '_inheriting', False) ) return func(token, serializer, incref=incref, **kwds) # This returns the Proxy 

A veces, esto puede ser deseable, pero a veces no, como en su caso. Puede ReduceProxy reemplazando la función ReduceProxy que realiza la eliminación en su progtwig:

 import multiprocessing.managers as m from multiprocessing import process def RebuildProxyNoReferent(func, token, serializer, kwds): ''' Function used for unpickling proxy objects. The Proxy object is always returned. ''' incref = ( kwds.pop('incref', True) and not getattr(process.current_process(), '_inheriting', False) ) return func(token, serializer, incref=incref, **kwds) m.RebuildProxy = RebuildProxyNoReferent # Monkey-patch it class Foo(object): def __init__(self): self.manager = MyManager() self.manager.register('Bar', Bar) self.manager.start() self.bar = self.manager.Bar() print(type(self.bar)) self.bar.set_proxy(self.bar) class Bar(object): def __init__(self): self.proxy = None def set_proxy(self, proxy): print("got {}".format(type(proxy))) self.proxy = proxy class MyManager(m.BaseManager): pass test = Foo() 

Si no quieres un parche de mono, también puedes subclase BaseProxy , aunque es un poco más de trabajo:

 import multiprocessing.managers as m from multiprocessing.managers import BaseProxy from multiprocessing import process def RebuildProxyNoReferent(func, token, serializer, kwds): ''' Function used for unpickling proxy objects. If possible the shared object is returned, or otherwise a proxy for it. ''' incref = ( kwds.pop('incref', True) and not getattr(process.current_process(), '_inheriting', False) ) return func(token, serializer, incref=incref, **kwds) class MyProxy(BaseProxy): _exposed_ = ("set_proxy",) def set_proxy(self, arg): self._callmethod('set_proxy', (arg,)) def __reduce__(self): ret = super(MyProxy, self).__reduce__() # RebuildProxy is the first item in the ret tuple. # So lets replace it, just for our proxy. ret = (RebuildProxyNoReferent,) + ret[1:] return ret class Foo(object): def __init__(self): self.manager = MyManager() self.manager.register('Bar', Bar, MyProxy) self.manager.start() self.bar = self.manager.Bar() print(type(self.bar)) self.bar.set_proxy(self.bar)