Maison > développement back-end > Golang > le corps du texte

Communication gRPC entre Go et Python

WBOY
Libérer: 2024-08-22 19:02:33
original
706 Les gens l'ont consulté

gRPC Communication Between Go and Python

gRPC est un framework d'appel de procédure à distance (RPC) puissant et hautes performances qui, bien qu'il soit moins couramment utilisé que REST, offre des avantages significatifs dans certains scénarios.

De plus, il est indépendant du langage et peut fonctionner dans n'importe quel environnement, ce qui en fait un choix idéal pour la communication de serveur à serveur.

Je n'entrerai pas dans les détails mais voici un lien général de gRPC. Je vais vous fournir un didacticiel pratique

Accéder au client gRPC 

Imaginons notre Go est client mais est un serveur comme pour l'application frontale React, Svelte etc.

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)
    }

 ...
}
Copier après la connexion

gRPC Communication Between Go and Python


À titre d'exemple, l'interface React télécharge un fichier, allez le traiter mais nous avons besoin de réponses d'Excel, nous utiliserons l'API GPT. Bien que cela puisse être fait avec Go, Python, en revanche, propose davantage de packages qui peuvent nous faciliter la vie, comme langchan_openai, pandas pour Excel, etc.


Commençons par l'installation de gRPC de préférence dans votre virtualenv .venv

$ 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"
Copier après la connexion

Ensuite, vous devez installer le tampon de protocole dans votre système d'exploitation. Vous pouvez le suivre ici.
Créons un répertoire proto dans lequel vous stockerez votre fichier tampon de protocole. Je le nommerai excel.proto et collez ceci :

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;
}
Copier après la connexion

Ce service gRPC, ExcelService, permet aux clients de télécharger un fichier en envoyant son nom et son contenu. Le serveur répond avec le même contenu de fichier. 

Pour Go, il est essentiel de passer go_package en Python, la ligne n'est pas nécessaire.

vscode-proto3 est une bonne extension à télécharger si vous utilisez VSCode.

Après tout cela, vous pouvez générer vos fichiers proto, je le préfère au même niveau que prot dir, pour cela exécutez cette commande :

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative proto/excel.proto

Si deux fichiers doivent être générés avec succès, éventuellement s'il y a beaucoup d'ajustements, ajoutez un Makefile et définissez-le comme proto + commande supérieure.

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
}
Copier après la connexion

Nous établissons une connexion pour écouter 50051 qui sera notre serveur Python, &pb.FileRequest a été généré auparavant à l'aide de la commande proto et maintenant nous importons les méthodes. Si vous courez, vous recevrez ? car le serveur Python n'est pas encore établi.

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"
Copier après la connexion

Serveur Python gRPC

Comme Python agira comme un serveur, l'approche sera légèrement différente mais en substance, le même fichier proto en dehors du champ du package n'est pas requis. Commençons par créer une base main.py sans gRPC juste pour donner un aperçu de la façon dont GPT remplira les questions dans Excel.

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
Copier après la connexion

C'est un script simple qui répondra aux questions que Go nous enverra mais le LOC est moindre grâce à la bibliothèque openai dédiée qui facilite les choses.


Nous commençons également par ajouter le répertoire proto avec le même fichier que ci-dessus, la section d'options peut être supprimée comme indiqué. Installez gRPC dans votre virtualenv de préférence et suivez ici l'installation pour la génération de protos que j'ai exécutée"

python3 -m grpc_tools.protoc --proto_path=proto --python_out=proto --grpc_python_out=proto proto/excel.proto
Copier après la connexion

Pour être dans le même niveau que mon répertoire proto pensez à ajouter __init.py!

Une fois les fichiers générés, continuons.

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()
Copier après la connexion

Nous définissons le serveur et ajoutons la classe ExcelService qui contient les méthodes générées par le fichier proto. Parce que nous recevons le fichier par octets, nous devons utiliser io byte reader et commencer le traitement ultérieur du fichier et remplir la deuxième colonne.

response = excel_pb2.FileResponse(file_content=output.read())
Copier après la connexion

À la fin nous revenons ☝️ pour que notre client Go le reçoive.

Pour pouvoir trouver des fichiers proto en python vous devez cependant définir un chemin d'exportation

export PYTHONPATH=$PYTHONPATH:mnt/c/own_dev/gRPC/server/proto

Exécution du client et du serveur

If all is good you can run

#First comes server

python3 -m main

#Then client

go run client.go Book1.xlsx
Copier après la connexion

Et vous devriez obtenir le fichier .xlsx mis à jour côté client Go.

Conclusion

Dans cet article, nous avons exploré les principes fondamentaux de la configuration de la communication gRPC entre le serveur Python et le client Go. En tirant parti de gRPC, nous avons établi un moyen transparent d'envoyer un fichier Excel d'une application Go à un serveur Python, de traiter le fichier à l'aide de l'API GPT d'OpenAI et de renvoyer le fichier modifié au client Go.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal