Maison > Article > développement back-end > Communication gRPC entre Go et 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
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) } ... }
À 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"
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; }
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 }
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"
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
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
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()
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())
À 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
If all is good you can run #First comes server python3 -m main #Then client go run client.go Book1.xlsx
Et vous devriez obtenir le fichier .xlsx mis à jour côté client Go.
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!