Go と Python 間の gRPC 通信

WBOY
リリース: 2024-08-22 19:02:33
オリジナル
706 人が閲覧しました

gRPC Communication Between Go and Python

gRPC は、強力で高性能なリモート プロシージャ コール (RPC) フレームワークであり、REST ほど一般的には使用されていませんが、特定のシナリオでは大きな利点を提供します。

さらに、言語に依存せず、あらゆる環境で実行できるため、サーバー間通信に理想的な選択肢となります。

詳しくは説明しませんが、gRPC の一般的なリンクは次のとおりです。実践的なチュートリアルを提供します

gRPC クライアントに移行する 

私たちの Go はクライアントですが、フロントエンド アプリ React、Svelte などのサーバーであることをイメージしてみましょう。

func getFirstArg() (string, error) {
    if len(os.Args) < 2 {
        return "", fmt.Errorf("expected 1 argument, but got none")
    }
    return os.Args[1], nil
}

func main() {
    filePath, err := getFirstArg()
    if err != nil {
        log.Fatalf("Failed to get file path from arguments: %v", err)
    }

    fileData, err := ioutil.ReadFile(filePath)
    if err != nil {
        log.Fatalf("Failed to read file: %v", err)
    }

 ...
}
ログイン後にコピー

gRPC Communication Between Go and Python


例として、React フロントエンドはファイルをアップロードし、Go でそれを処理しますが、Excel からの回答が必要なので、GPT API を使用します。 Go でも実行できますが、一方で Python には、langchan_openai、Excel 用のパンダなど、私たちの生活を楽にするパッケージがたくさんあります。


できれば virtualenv .venv に gRPC をインストールすることから始めましょう

$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
$ export PATH="$PATH:$(go env GOPATH)/bin"
ログイン後にコピー

次に、OS にプロトコル バッファをインストールする必要があります。
プロトコル バッファ ファイルを保存する proto ディレクトリを作成しましょう。それに excel.proto という名前を付けて、これを貼り付けます:

syntax = "proto3";
option go_package = "client-gRPC/proto";
service ExcelService {
    rpc UploadFile(FileRequest) returns (FileResponse);
}
message FileRequest {
    string file_name = 1;
    bytes file_content = 2;
}
message FileResponse {
    bytes file_content = 1;
}
ログイン後にコピー

この gRPC サービスである ExcelService を使用すると、クライアントは名前と内容を送信してファイルをアップロードできます。サーバーは同じファイル内容で応答します。 

Go の場合、Python で go_package を渡すことが不可欠です。この行は必要ありません。

vscode-proto3 は、VSCode を使用する場合にダウンロードするのに適した拡張機能です。

これらすべてが完了したら、proto ファイルを生成できます。prot dir と同じレベルに置くことをお勧めします。そのためには、次のコマンドを実行します。

プロトコル --go_out=。 --go_opt=paths=source_relative --go-grpc_out=。 --go-grpc_opt=paths=source_relative proto/excel.proto

成功すると 2 つのファイルが生成されますが、多くの調整がある場合はオプションで Makefile を追加し、proto + upper コマンドとして定義します。

import (
    ....

    "google.golang.org/grpc"
    pb "client-gRPC/proto"
    "github.com/xuri/excelize/v2"
)

func main() {
    ....

    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("Failed to connect to gRPC server: %v", err)
    }
    defer conn.Close()

    client := pb.NewExcelServiceClient(conn)

    req := &pb.FileRequest{
        FileName:    filePath,
        FileContent: fileData,
    }

    res, err := client.UploadFile(context.Background(), req)
    if err != nil {
        log.Fatalf("Failed to upload file: %v", err)
    }

    outputFile := "output.xlsx"
    err = saveBytesAsExcel(outputFile, res.FileContent)
    if err != nil {
        log.Fatalf("Failed to save bytes as Excel file: %v", err)
    }

    fmt.Printf("Excel file saved as: %s\n", outputFile)
}

func saveBytesAsExcel(filePath string, fileContent []byte) error {
    f, err := excelize.OpenReader(bytes.NewReader(fileContent))
    if err != nil {
        return fmt.Errorf("failed to open Excel file: %v", err)
    }

    if err := f.SaveAs(filePath); err != nil {
        return fmt.Errorf("failed to save Excel file: %v", err)
    }
    return nil
}
ログイン後にコピー

Python サーバーとなる 50051 をリッスンするための接続を作成します。&pb.FileRequest は proto コマンドを使用して事前に生成されており、今メソッドをインポートしています。走れば受信できますか? Python サーバーがまだ確立されていないため。

Failed to upload file: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp 127.0.0.1:50051: connect: connection refused"
ログイン後にコピー

Python gRPC サーバー

Python はサーバーとして機能するため、アプローチは少し異なりますが、本質的にはパッケージフィールドとは別に同じプロトファイルは必要ありません。 GPT が Excel に質問をどのように入力するかを一目でわかるように、gRPC を使用せずにベースの main.py を作成することから始めましょう。

import os
import openai
import pandas as pd
from dotenv import load_dotenv

def get_answer_from_gpt(apikey: str, question: str):
    openai.api_key = apikey
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": question}
        ]
    )
    return response['choices'][0]['message']['content'].strip()

def answer_questions_df(df: pd.DataFrame, apikey: str):
    answers = []

    for question in df.iloc[:, 0]: 
        answer = get_answer_from_gpt(apikey, question)
        answers.append(answer)
    return answers

if __name__ == "__main__":
    load_dotenv()

    openai_api_key = os.getenv("OPENAI_API_KEY", "OpenAI API key hasn't been set.")

    df = pd.read_excel('Book1.xlsx')

    df['Answer'] = answer_questions_df(df, openai_api_key
ログイン後にコピー

Go が送信する質問に答えるシンプルなスクリプトですが、専用の openai ライブラリにより LOC が少なくなり、簡単になります。


まず、上記と同じファイルで proto dir を追加します。オプション セクションは、説明したように削除できます。できれば virtualenv に gRPC をインストールし、ここで私が実行したプロト生成のインストールに従ってください。

python3 -m grpc_tools.protoc --proto_path=proto --python_out=proto --grpc_python_out=proto proto/excel.proto
ログイン後にコピー

私の proto ディレクトリと同じレベルにするには、忘れずに __init.py を追加してください!

ファイルが生成されたら、次に進みましょう。

import io
import grpc
from proto import excel_pb2_grpc as excel_grpc
from proto import excel_pb2

class ExcelService(excel_grpc.ExcelServiceServicer):
    def UploadFile(self, request, context):
        try:
            # Convert bytes to a file-like object
            file_like_object = io.BytesIO(request.file_content)

            # Load the workbook from the file-like object
            workbook = openpyxl.load_workbook(file_like_object)

            # Access the first sheet (or use appropriate logic to get the sheet you need)
            sheet = workbook.active

            # Convert the sheet to a DataFrame
            data = sheet.values
            columns = next(data)  # Get the header row
            df = pd.DataFrame(data, columns=columns)

            print("Loaded DataFrame:")
            print(df.head())

            # Ensure that the DataFrame is not empty and has questions
            if df.empty or df.shape[1] < 1:
                print("DataFrame is empty or does not have the expected columns.")
                return excel_pb2.FileResponse(file_content=b'')

            # Get answers and add them to the DataFrame
            answers = answer_questions_df(df, openai_api_key)
            df['Answer'] = answers

            # Write the updated DataFrame back to a BytesIO object
            output = io.BytesIO()
            with pd.ExcelWriter(output, engine='openpyxl') as writer:
                df.to_excel(writer, index=False, sheet_name='Sheet1')

            # Reset the buffer's position to the beginning
            output.seek(0)

            # Return the modified file content
            response = excel_pb2.FileResponse(file_content=output.read())
            return response
        except Exception as e:
            print(f"Error processing file: {e}")
            return excel_pb2.FileResponse(file_content=b'')

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    excel_grpc.add_ExcelServiceServicer_to_server(ExcelService(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    print("Server running on port 50051.")
    server.wait_for_termination()

if __name__ == "__main__":
    load_dotenv()

    openai_api_key = os.getenv("OPENAI_API_KEY", "OpenAI API key hasn't been set.")

    serve()
ログイン後にコピー

サーバーを定義し、proto ファイルによって生成されたメソッドを含む ExcelService クラスを追加します。ファイルをバイト単位で受信するため、io バイト リーダーを使用してファイルのさらなる処理を開始し、2 番目の列に入力する必要があります。

response = excel_pb2.FileResponse(file_content=output.read())
ログイン後にコピー

最後に、Go クライアントが受け取るために ☝️ を返します。

Python で proto ファイルを見つけられるようにするには、エクスポート パスを定義する必要があります

エクスポート PYTHONPATH=$PYTHONPATH:mnt/c/own_dev/gRPC/server/proto

クライアントとサーバーの実行

If all is good you can run

#First comes server

python3 -m main

#Then client

go run client.go Book1.xlsx
ログイン後にコピー

そして、Go クライアント側で更新された .xlsx ファイルを取得する必要があります。

結論

この記事では、Python サーバーと Go クライアント間の gRPC 通信の設定の基礎について説明しました。 gRPC を活用することで、Go アプリケーションから Python サーバーに Excel ファイルを送信し、OpenAI の GPT API を使用してファイルを処理し、変更されたファイルを Go クライアントに返すシームレスな方法を確立しました。

以上がGo と Python 間の gRPC 通信の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート