• python对于grpc的简单操作(二)


    今天介绍proto文件的一些关键字和一些常见的数据类型以及它们如何在客户端和服务端传输,传值

    (一).proto的常见关键字

    常见关键字解释
    syntax指定protobuf版本
    package包名,可以不填
    import导入一些插件,一般go用的比较多
    message定义传输的数据结构
    service定义服务
    rpc定义服务中的方法
    stream定义方法中数据的传输方式为流传输

    (二).proto中message的常见数据类型

    常见数据类型解释
    string默认值为空白字符, 字符串必须始终包含UTF-8编码或7位ASCII文本。
    int32/int64对应长短整型,默认值是0
    boolbool类型
    float浮点型
    repeated对应于python列表类型,但不完全一样,数据类型只能为一种,不能动态变换
    map对应于python字典类型,但不完全一样,数据类型只能为一种,不能动态变换
    bytes比特类型,默认值是空白字节,可能包含任何字节序列

    PS:其实严格来说repeated不是数据类型,应该属于关键字,但可以通过repeated关键字实现python列表功能

    (三)示例proto文件

    syntax = "proto3";   // 指定protobuf版本
    
    package test;   // 此文件的标识符,不添加也可以,以防止协议消息类型之间的名称冲突
    
    // 定义消息结构类型,字段编号,可不从1开始,但不能重复,request为数据结构名,可自由定义
    message request {
    	int32 age = 1;//年龄
    	string name = 2;//姓名
    	hobbies hobby = 3;//爱好(外部引用)
    	map<string, string> info = 4;//包含血型,性别
    	repeated int32 height_weight = 5; //包含身高,体重
    	openings opening = 6;//内部引用
    
    	message openings { //开场白
    	    string words = 1; //大家好,我是连续时长两年半的{},喜欢ctrl,music,你干嘛~
    	}
    }
    
    message hobbies {//爱好
        bool sing = 1;                //会唱?
        bool dance = 2;               //会跳?
        bool rap = 3;                 //会rap?
        bool basketball = 4;          //会篮球?
    }
    
    
    
    // 定义消息结构类型,数据后面的编号不能重复,response为数据结构名,可自由定义
    message response {
    	string message = 1;
    }
    
    //定义服务,下面定义的这种为最简单的rpc服务,客户端发起请求,服务端返回结果
    service UserInfo {
    	rpc Info (request) returns (response) {}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    server.py

    from concurrent import futures
    import logging
    
    import grpc
    import test_pb2
    import test_pb2_grpc
    
    
    class UserInfo(test_pb2_grpc.UserInfoServicer):
        def Info(self, request, context):
            print(request)
    
            # print(request.age)  # 点取值
            # print(request.name)  # 点取值
            # print(request.hobby)  # 点取值
            # print(request.info)  # 字典取值
            # print(request.height_weight)  # 列表取值
            # print(request.opening)  # 点取值
    
            return test_pb2.response(message='大家好,我是连续时长三年半的{},喜欢ctrl。{}'.format(request.name, request.opening.words))
    
    
    def serve():
        server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))  # 开启多线程
        test_pb2_grpc.add_UserInfoServicer_to_server(UserInfo(), server)  # 注册本地服务
        server.add_insecure_port('[::]:10086')  # 指定端口以及IP
        # server.add_insecure_port('0.0.0.0:10086')# 指定端口以及IP
        server.start()  # 启动服务器 start()是非阻塞的, 将实例化一个新线程来处理请求
        server.wait_for_termination()  # 阻塞调用线程,直到服务器终止
    
    
    if __name__ == '__main__':
        logging.basicConfig()
        serve()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    client.py

    import logging
    
    import grpc
    import test_pb2
    import test_pb2_grpc
    
    
    def run():
        with grpc.insecure_channel('localhost:10086') as channel:
            client = test_pb2_grpc.UserInfoStub(channel)  # 客户端使用Stub类发送请求,参数为频道,为了绑定链接
    
            response = client.Info(test_pb2.request(age=0,
                                                    name='张三',
                                                    hobby=test_pb2.hobbies(sing=True, dance=True, rap=True, basketball=True),
                                                    info={'blood_type': 'A', 'gender': 'female'},
                                                    height_weight=[184, 60],
                                                    opening=test_pb2.request.openings(words='music,你干嘛~')
                                                    ))
            print("用户信息:" + response.message)
    
    
    if __name__ == '__main__':
        logging.basicConfig()
        run()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    运行效果
    在这里插入图片描述

    可以看见,上面有乱码,其实都是中文,但这个没关系,只有在你打印request时,里面的数据才会乱码,当你取出里面的独立元素是没有乱码的。

    (四)结语

    如果有什么错误的地方,还请大家批评指正。最后,希望小伙伴们都能有所收获。写这些,仅记录自己学习python操作grpc的过程
    在这里插入图片描述

  • 相关阅读:
    设计原则总结
    VS Qt 使用linguits(Qt语言家)生成.ts的翻译文件并翻译使用的详细过程
    初识二叉搜索树
    base_lcoal_planner的LocalPlannerUtil类中getLocalPlan函数详解
    LabVIEW开发航天器模拟器的姿态控制和反作用轮动量管理
    RPA要不要学习,真的能解放双手吗?
    .NET MAUI – 一个代码库,多个平台
    动画一:过渡(超详细!)
    MindSponge分子动力学模拟——Constraint约束(2023.09)
    ubuntu安全扩展交换内存swap memory
  • 原文地址:https://blog.csdn.net/weixin_43810267/article/details/126153456