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
4

2 回答 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    
于 2018-08-21T13:01:23.017 回答
1

这不应该发生在原语(整数、字符串等)上,但肯定会发生在一般对象上。您在服务器中需要做的是obtain对象,它在服务器进程中创建它们的副本,不再依赖于保留在客户端进程中的引用。

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在客户端进程中使用来实现。

于 2015-10-08T05:46:07.167 回答