1. 程式人生 > >Python:GRPC介面編寫之如何編寫服務端與客戶端

Python:GRPC介面編寫之如何編寫服務端與客戶端

上次我們講了如何生成ABC_pb2.py 和 ABC_pb2_grpc.py,這次我們來講述如何使用這兩個檔案來編寫服務端、客戶端,完成遠端呼叫。(其實服務端有些部分的編寫我也沒太明白就照搬了,但是你按我說的去修改自己的檔案,不出意外是能正常跑的)

下面ABC_pb2.py簡稱pd2檔案,ABC_pb2_grpc.py簡稱grpc檔案。

因為我在學習介面編寫的時候,發現網上一些示例的引數名稱寫的都一模一樣,所以寫函式的時候我繞了一段時間;其次就是他們寫的例子很簡單,我的呼叫稍複雜些,所以多出來的部分不知道該怎麼寫。

所以這次我專門編寫了例子,引數名儘量使用個性化的、不相同的,以便大家區分每個部分的作用和位置。

我會試著共享這幾個檔案,文中用到哪些部分我會截圖放上,主要就是參考proto、grpc檔案中的函式及變數名。

呃……好像資源需要積分才能下載。那我把我的檔案程式碼都附在文章最後吧,給大家省一點哈哈。

我的proto檔案:lwz_model.proto

編譯出的兩個檔案:lwz_model_pb2_grpc.py, lwz_model_pb2.py

服務端:lwz_sever.py

客戶端:lwz_client.py

一、服務端、客戶端所用得到的函式及變數名

其實如果將我給的服務端、客戶端相應部分進行替換,就可以簡單的改寫成你自己的服務端與客戶端。那麼接下來就簡單列出替換所用到的函式及變數名。

1、proto檔案中的部分

其實proto檔案的結構你梳理清楚了,難度就減少了一大半了。

2、grpc檔案中的部分

這個檔案我沒怎麼去理解,只是簡單的找到所需部分就用了。那這個檔案我把所需部分標號,下面講的時候以“grpc1”來標註,到時候你們直接在自己的檔案中找到對應的部分就可以用了,你肯定會找到和這個長得差不多的你相信我。

我發現,其實grpc1好像就是  服務名Stub ,grpc2是 服務名Servicer , grpc3是 add_服務名Servicer_to_server

我算上這個例子才一共寫了兩個介面,不一定總結的對,你們可以確認一下。

二、服務端編寫

為了方便標註,我是把程式碼截圖後在圖片上寫註釋的,紫色部分基本是你要照搬的,或者你自定義的東西,可改可不改的;橙色部分是你必須根據你自己的檔案進行替換修改的地方,格式我都已經在旁邊寫好了,對應上小節截圖中約定的名稱找你對應的部分。

三、客戶端編寫

跟服務端一樣,紫色照搬,橙色自改。

四、兩個客戶端怎麼使用?

現在我們已經編寫好了所有的檔案,如何開始提供服務,開始呼叫呢?

執行你的服務端,再執行你的客戶端就可以了哈哈。

執行客戶端以後,他會一直處於執行狀態。這屬於正常現象,如果沒有這樣你才該檢查自己的程式。

然後再執行你的客戶端,我在服務端加了一個print函式,每次呼叫,就會print出"tansfer"。

下面是一次成功呼叫後,服務端和客戶端的情況:

服務端

客戶端

成功啦~

以上。

後記:

大家看我的部落格可能覺得我說話羅裡吧嗦的,事實上我確實不太會教別人。其實我就是覺得如果當時有人這樣教我的話,我會省很多麻煩,所以我就儘量寫的詳細,但是大家可能覺得有些部分很簡單,我還在用大篇幅去說明。那大家只要能在文章裡找到一點點自己能用得到的東西我就很開心了,我標題就儘量寫明確,大家摘重點看吧,比較節省時間。

我個人的程式設計技術不是特別好,所以寫的可能不全面還有漏洞,歡迎大家給我指出來,我也學習和進步一下。祝大家越來越強!

哈哈哈哈發現自己檔名的server全都拼錯了,懶得改了大家將就看……

附件程式碼:

資源連結是CSDN,包含proto檔案及編譯出的兩個檔案,服務端、客戶端。

強烈建議自己動動手自己複製下面的程式碼,不是很費事的,勤儉持家哈哈。

proto檔案(檔名:lwz_model.proto)

// Filename: lwz_model.proto

syntax="proto3";
package lwz_example;
service model{
    rpc lwz_show(lwz_Request) returns (lwz_Response){}
}


message lwz_Request {
    string index = 1;
    string name = 2;
    int64 age = 3;
}

message lwz_Response{
    string stu_class = 1;
    int64 grade = 2;
}


服務端(檔名:lwz_sever.py)

#!/usr/bin/env python
# coding:utf-8
import grpc
import time
from concurrent import futures
import lwz_model_pb2_grpc, lwz_model_pb2

_ONE_DAY_IN_SECONDS = 60 * 60 * 24
_HOST = 'localhost'
_PORT = '6060'

class model(lwz_model_pb2_grpc.modelServicer):
    #### 隨意定義-封裝好的函式 #####
    def serch_student_class(self, index):
        if index == '201801':
            student_class = '5'
            return student_class

    def serch_student_grade(self,name ,age):
        if name =='lwz' and age == 100:
            student_grade = 100
            return student_grade

    ##### 真正重要的-輸出函式 #####
    def lwz_show(self, request, context):
        index = request.index
        name = request.name
        age = request.age

        student_class = self.serch_student_class(index)
        student_grade = self.serch_student_grade(name ,age)
        print ("tansfer")
        return lwz_model_pb2.lwz_Response(stu_class = student_class,grade = student_grade)

def serve():
    grpcServer = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    lwz_model_pb2_grpc.add_modelServicer_to_server(model(), grpcServer)
    grpcServer.add_insecure_port(_HOST + ':' + _PORT)
    grpcServer.start()
    try:
        while True:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        grpcServer.stop(0)

if __name__ == '__main__':
    serve()

客戶端(檔名:lwz_client.py)

import grpc
import lwz_model_pb2_grpc, lwz_model_pb2

_HOST = 'localhost'
_PORT = '6060'

def run():
    conn = grpc.insecure_channel(_HOST + ':' + _PORT)
    client = lwz_model_pb2_grpc.modelStub(channel=conn)
    response = client.lwz_show(lwz_model_pb2.lwz_Request(index = '201801',name = 'lwz',age = 100))
    print("received: " + response.stu_class)
    print("received: " + str(response.grade))

if __name__ == '__main__':
    run()