gpt4 book ai didi

Python:如何传递 Autoproxy 对象

转载 作者:太空宇宙 更新时间:2023-11-03 17:45:56 24 4
gpt4 key购买 nike

我需要将一个对象的代理传递给另一个对象,但每当我这样做时,所有其他对象获取的都是代理的指示对象,而不是代理本身。这与我想做的事情类似:

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()

每当我执行此操作时,self.proxy 中的值都是我创建的 Foo 实例,而不是管理器返回的代理。

最佳答案

这是因为设计缺陷,或者可能是 a bug ,以 Proxy 实例被 unpickled 的方式。现在,如果 unpickle 代码看到您正在 Manager 内运行,它会在您 unpickle 时为您提供指示对象,而不是 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

有时这可能是可取的,但有时却不是,就像您的情况一样。您可以通过替换在程序中执行 unpickle 操作的 ReduceProxy 函数来解决此问题:

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()

如果你不想打猴子补丁,你也可以继承BaseProxy,尽管这需要更多的工作:

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)

关于Python:如何传递 Autoproxy 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29788809/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com