0

我正在尝试按照本文档访问 RPyC 调用上的公共属性,但没有看到它像文档中提到的那样工作。

文档说,如果您不指定protocol_config={'allow_public_attrs': True,},公共属性,即使是内置数据类型也将无法访问。但是,即使我们指定了这一点,嵌套数据结构的公共属性也无法访问?

RPyC 服务器代码。

import pickle
import rpyc

class MyService(rpyc.Service):
    def on_connect(self, conn):
        # code that runs when a connection is created
        # (to init the service, if needed)
        pass

    def on_disconnect(self, conn):
        # code that runs after the connection has already closed
        # (to finalize the service, if needed)
        pass

    def exposed_get_answer(self): # this is an exposed method
        return 42

    exposed_the_real_answer_though = 43     # an exposed attribute

    def get_question(self):  # while this method is not exposed
        return "what is the airspeed velocity of an unladen swallow?"

    def exposed_hello(self, collection):
        print ("Collection is ", collection)
        print ("Collection type is ", type(collection).__name__)
        for item in collection:
            print ("Item type is ", type(item).__name__)
            print(item)

    def exposed_hello2(self, collection):
        for item in collection:
            for key, val in item.items():
                print (key, val)

    def exposed_hello_json(self, collection):
        for item in collection:
            item = json.loads(item)
            for key, val in item.items():
                print (key, val)


if __name__ == "__main__":
    from rpyc.utils.server import ThreadedServer
    t = ThreadedServer(
            MyService(),
            port=3655,
            protocol_config={'allow_public_attrs': True,}
            )
    t.start()

客户端调用

>>> import rpyc
>>> rpyc.__version__
(4, 0, 2)
>>> c = rpyc.connect('a.b.c.d', 3655)  ; client=c.root

# Case 1 如果数据是嵌套结构(使用内置数据类型),它不起作用。

>>> data
[{'a': [1, 2], 'b': 'asa'}]
>>> client.hello2(data)
...
AttributeError: cannot access 'items'
========= Remote Traceback (2) =========
Traceback (most recent call last):
  File "/root/lydian.egg/rpyc/core/protocol.py", line 329, in _dispatch_request
    res = self._HANDLERS[handler](self, *args)
  File "/root/lydian.egg/rpyc/core/protocol.py", line 590, in _handle_call
    return obj(*args, **dict(kwargs))
  File "sample.py", line 33, in exposed_hello2
    for key, val in item.items():
  File "/root/lydian.egg/rpyc/core/netref.py", line 159, in __getattr__
    return syncreq(self, consts.HANDLE_GETATTR, name)
  File "/root/lydian.egg/rpyc/core/netref.py", line 75, in syncreq
    return conn.sync_request(handler, proxy, *args)
  File "/root/lydian.egg/rpyc/core/protocol.py", line 471, in sync_request
    return self.async_request(handler, *args, timeout=timeout).value
  File "/root/lydian.egg/rpyc/core/async_.py", line 97, in value
    raise self._obj
_get_exception_class.<locals>.Derived: cannot access 'items'

案例2:解决方法,使用json(穷人的泡菜)将嵌套数据作为字符串传递并在服务器端解码。

>>> jdata = [json.dumps({'a': [1,2], 'b':"asa"})].  
>>> client.hello_json(jdata) # Prints following at remote endpoint.
a [1, 2]
b asa

案例 3:有趣的是,在第一级内置项目是可以访问的,就像 hello 方法一样。但是在嵌套数据上调用它会出错。

>>> client.hello([1,2,3,4])  # Prints following at remote endpoint.
Collection is  [1, 2, 3, 4]
Collection type is  list
Item type is  int
1
Item type is  int
2
Item type is  int
3
Item type is  int
4

我有问题的解决方法/解决方案(上面的案例 2),但正在寻找关于为什么不允许这样做或者它是否是错误的解释。感谢您的投入。

4

1 回答 1

0

该问题与嵌套数据无关。

您的问题是您不允许在客户端使用公共属性。解决方案很简单:

c = rpyc.connect('a.b.c.d', 3655, config={'allow_public_attrs': True})

请记住,rpyc 是一种对称协议(请参阅https://rpyc.readthedocs.io/en/latest/docs/services.html#decoupled-services)。

在您的情况下,服务器尝试访问客户端的对象,因此必须在客户端设置allow_public_attrs 。实际上,对于您的具体示例,无需在服务器端设置allow_public_attrs

关于案例3:

在行for item in collection:中,服务器尝试访问两个字段:collection.__iter__collection.__next__。默认情况下,这两个字段都被视为“安全属性”,这就是您在那里没有出错的原因。要检查 rpyc 中的默认配置字典:

>>> import rpyc
>>> rpyc.core.protocol.DEFAULT_CONFIG
于 2020-12-19T22:57:55.227 回答