如何将弱引用转换为强引用?

3
我使用 RPyC 连接到一个客户端,并调用了一个带参数对象的服务暴露方法。我想要使用这个对象并对其进行操作,但是这个对象是弱引用的。当我想要访问它的数据时,会出现一个 ReferenceError 的错误,提示对象“弱引用对象已经不存在”。
如何安全地保存一个带有弱引用的对象,避免被垃圾回收?如何将其转换为强引用?
server.py (发送消息)
conn = rpyc.connect(ip,port)
bgsrv = rpyc.BgServingThread(conn)
conn.root.my_remote_method(a, b, c)  # a,b,c are integer, strings etc.
time.sleep(0.2)
bgsrv.stop()
conn.close()

client.py(处理数据并将其放入队列中)

class MessageService(Service):
    def exposed_my_remote_method(self, a, b, c):
        ThreadedClient.queue.put([a,b,c])

other.py(读取队列)

def read_queue(self):
    """ Handle all the messages currently in the queue (if any) """
    while ThreadedClient.queue.qsize():
        try:
            msg = ThreadedClient.queue.get(0)
            self.read_message(msg)
        except Queue.Empty:
            pass

def read_message(self, msg):
    # do something with the data of a, b, c
    res = msg[0] + xy # ReferenceError
2个回答

2
我使用了以下例程解决了弱引用问题(以及缺失属性的问题):
def rpyc_deep_copy(obj):
    """
    Makes a deep copy of netref objects that come as a result of RPyC remote method calls.
    When RPyC client obtains a result from the remote method call, this result may contain
    non-scalar types (List, Dict, ...) which are given as a wrapper class (a netref object). 
    This class does not have all the standard attributes (e.g. dict.tems() does not work) 
    and in addition the objects only exist while the connection is active. 
    To have a retuned value represented by python's native datatypes and to by able to use it 
    after the connection is terminated, this routine makes a recursive copy of the given object. 
    Currently, only `list` and `dist` types are supported for deep_copy, but other types may be added easily.
    Example:
        s = rpyc.connect(host1, port)
        result = rpyc_deep_copy(s.root.remote_method())
        # if result is a Dict:
        for k,v in result.items(): print(k,v)
    """
    if (isinstance(obj, list)):
        copied_list = []
        for value in obj: copied_list.append(rpyc_deep_copy(value))
        return copied_list
    elif (isinstance(obj, dict)):
        copied_dict = {}
        for key in obj: copied_dict[key] = rpyc_deep_copy(obj[key])
        return copied_dict
    else:
        return obj
    #end if
#end def    

1

基本类型(如整型、字符串等)不会出现这种情况,但是一般对象可能会。在服务器端,您需要获取对象,这将在服务器进程中创建它们的副本,不再依赖于客户端进程中保留的引用。

class MessageService(Service):
    def exposed_my_remote_method(self, a, b, c):
        a,b,c = rpyc.classic.obtain([a,b,c])
        ThreadedClient.queue.put([a,b,c])

在客户端过程中,也可以使用deliver来实现此目的。


2
添加了这些代码后,我又遇到了一个错误:“ValueError: pickling is disabled”。我在question26899050上找到了解决方案,即添加conn = rpyc.connect(ip, port, config={"allow_public_attrs": True, "allow_pickle":True}) - Paula

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接