如何将弱引用更改为强引用?

时间:2015-10-07 15:31:36

标签: python-2.7 weak-references strong-references rpyc

我使用RPyC连接到客户端,并使用参数对象调用Service公开的方法。我想从公开的方法中获取此对象并使用它做一些事情,但是这个对象是弱引用的,当时我想访问它的数据:我得到一个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 个答案:

答案 0 :(得分: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来实现。

答案 1 :(得分:1)

我使用以下例程解决了周参考的问题(以及属性缺失的问题):

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