cara是cap'n proto的替代rpc api。
cara的Python项目详细描述
cara是cap'n proto的替代rpc api。Read the docs!
创建原因
PyCAPNP是一个直的C++转换,而这是伟大的,所有的, 不是Python。它还使用capnp的rpc层和friends,即 从零开始,并不是很成熟,而有大量的rpc 层、事件循环等已经在python中并且维护良好。
要求
要通过setup.py(或pip)安装,capnproto安装必须是 可通过pkg配置定位。通过普通的“sudo make install”安装 应该可以,其他情况还没有测试过。
用法
首先,从.capnp文件生成代码:
capnp compile -ocara my_structs.capnp
然后导入它们:
import my_structs_capnp
示例
my_structs.capnp
struct MyStruct { field @0 :Text; nested @1 :NestedStruct; struct NestedStruct { integer @0 :Int32; } }
python用法
import my_structs_capnp my_structs_capnp.MyStruct({'field': 'some text for here'}) # -- or -- m = my_structs_capnp.MyStruct.Create(field='some different text') # All the classes masquerade as python builtins, like dict: msgpack.packb(m) == b'\x81\x00\xb3some different text' # But it's slightly different... Look at Field Shrinking below to # understand
pseud集成
还有pseud集成。 pseud支持tornado和gevent,但python 3上只有tornado,所以 这些例子使用了龙卷风。如果使用python 2,欢迎使用 格文特。
第一个要求是调用cara-pseud.setup-server 在您的服务器和客户机上的cara-pseud.setup\u客户机上。两者都有一次 调用时,可以启动服务器和客户端。对于服务器, 向要导出的类或函数注册接口。为了 客户端,用要使用的接口包装客户端对象 作为。这个api允许服务器导出多个接口和一个客户机 使用任意数量。
示例
my_ifaces.capnp
interface SimpleEcho { echo (text :Text) -> (text :Text); } interface BackAndForth { interface Callback { callback (callback :Callback) -> (result :Text); } callMeMaybe (callback :Callback) -> (); otherFunc () -> (); }
python用法:
from cara import cara_pseud from my_ifaces_capnp import SimpleEcho, BackAndForth @tornado.gen.coroutine def create_server(): server = pseud.Server(...) server.bind(...) cara_pseud.setup_server(server) yield server.start() # A function can be used to implement an interface with a single # method. The name doesn't have to match either. @cara_pseud.register_interface(server, SimpleEcho) def func(text): return text # If an interface has multiple methods, a class is necessary. It also has # to implement all the methods, but its name can be anything, too. # It can subclass the interface or object, but if you choose the # interface, the register_interface call can infer it from the class # definition. @cara_pseud.register_interface(server) class Server(BackAndForth): def callMeMaybe(self, callback): # You can even use a lambda as an interface. callback(lambda: 'internal callback') def otherFunc(self): pass @tornado.gen.coroutine def create_client(): server = pseud.Client(...) server.connect(...) cara_pseud.setup_client(server) yield client.start() echo_iface = SimpleEcho(client) result = yield echo_iface.echo('test') assert result == 'test' # Now let's mess with this exported interface. back_and_forth = BackAndForth(client) # This is a special combination of fortunate accidents. A method with one # argument that is an interface with one method can be called like a # decorator. Though, you need to yield it still. @back_and_forth.callMeMaybe def callback(callback=None): result = yield callback() assert result == 'internal callback' yield callback io_loop.add_callback(create_server) io_loop.add_callback(create_client) io_loop.start()
磁场收缩
# Notice there's no mention of 'field' in the result: m = my_structs_capnp.MyStruct({'field': 'some text for here'}) msgpack.packb(m) == b'\x81\x00\xb3some different text' # Yet it's there when we pack the object directly. m = {'field': 'some different text'} msgpack.packb(m) == b'\x81\xa5field\xb3some different text'
不同之处在于,cara结构使用字段的序号 而不是他们的名字。只有在发送 将字节打包到另一个不使用cara的系统。如果你派 它回到卡拉,它会正确地打开字段,你可以使用它 就像原作一样。
original = my_structs_capnp.MyStruct.Create(nested={'integer': 2}) packed = msgpack.packb(original) unpacked = msgpack.unpackb(packed) # --> {1: {0: 2}} result = my_structs_capnp.MyStruct(unpacked) # --> MyStruct({nested: NestedStruct({integer: 2})})
这允许我们将结构序列化为更小的bytestring, 尤其是因为0-127在msgpack中变成了一个字节。只要你的 capnp模式更改是向后兼容的,您可以 反序列化并查找字段号以获取适当的类型。