Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Komunikasi gRPC Antara Go dan Python

Komunikasi gRPC Antara Go dan Python

WBOY
WBOYasal
2024-08-22 19:02:33680semak imbas

gRPC Communication Between Go and Python

gRPC ialah rangka kerja Panggilan Prosedur Jauh (RPC) yang berkuasa dan berprestasi tinggi yang, walaupun kurang biasa digunakan berbanding REST, menawarkan kelebihan ketara dalam senario tertentu.

Selain itu ia adalah bahasa agnostik dan boleh dijalankan dalam mana-mana persekitaran, menjadikannya pilihan ideal untuk komunikasi pelayan-ke-pelayan.

Saya tidak akan menyelidiki secara keseluruhannya tetapi berikut ialah pautan umum gRPC. Saya akan berikan tutorial

Pergi ke klien gRPC 

Mari gambarkan Go kami adalah pelanggan tetapi merupakan pelayan untuk apl frontend React, Svelte dsb.

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


Sebagai contoh React frontend memuat naik fail, Pergi proseskannya tetapi kami memerlukan jawapan daripada excel kami akan menggunakan API GPT. Walaupun ia boleh dilakukan dengan Go, Python sebaliknya mempunyai lebih banyak pakej yang boleh memudahkan kehidupan kita seperti langchan_openai, panda untuk excel dan sebagainya.


Mari mulakan dengan pemasangan gRPC sebaik-baiknya dalam virtualenv .venv anda

$ 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"

Seterusnya anda harus memasang penimbal protokol dalam OS anda boleh mengikutinya di sini.
Mari buat dir proto di mana anda akan menyimpan fail penimbal protokol anda. Saya akan namakannya sebagai excel.proto dan tampal ini:

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

Perkhidmatan gRPC ini, ExcelService, membenarkan pelanggan memuat naik fail dengan menghantar nama dan kandungannya. Pelayan bertindak balas dengan kandungan fail yang sama. 

Untuk Go adalah penting untuk memasukkan go_package dalam Python baris tidak diperlukan.

vscode-proto3 ialah sambungan yang baik untuk dimuat turun jika anda menggunakan VSCode.

Selepas semua ini, anda boleh menjana fail proto anda, saya lebih sukakannya dalam tahap yang sama seperti prot dir, untuk itu jalankan arahan ini:

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

Jika dua fail yang berjaya harus dijana, secara pilihan jika terdapat banyak pelarasan tambahkan Makefile dan takrifkannya sebagai proto + arahan atas.

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
}

Kami membuat sambungan untuk mendengar 50051 yang akan menjadi pelayan Python kami, &pb.FileRequest telah dijana sebelum ini dengan menggunakan arahan proto dan kini kami mengimport kaedah tersebut. Jika anda berlari anda akan menerima? disebabkan pelayan Python belum ditubuhkan lagi.

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"

Pelayan gRPC Python

Oleh kerana python akan bertindak sebagai pelayan pendekatan akan berbeza sedikit tetapi pada dasarnya fail proto yang sama selain daripada medan pakej tidak diperlukan. Mari mulakan dengan mencipta asas main.py tanpa gRPC hanya untuk memberi pandangan tentang cara GPT akan mengisi soalan dalam 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

Skrip ringkas yang akan menjawab soalan yang akan dihantar oleh Go kepada kami tetapi LOC kurang disebabkan perpustakaan openai khusus yang memudahkannya.


Kami bermula dengan menambah dir proto dengan fail yang sama seperti di atas bahagian pilihan boleh dialih keluar seperti yang dibincangkan. Pasang gRPC dalam virtualenv anda sebaik-baiknya dan ikuti di sini pemasangan untuk generasi proto yang saya jalankan"

python3 -m grpc_tools.protoc --proto_path=proto --python_out=proto --grpc_python_out=proto proto/excel.proto

Untuk berada dalam lvl yang sama dengan direktori proto saya ingat untuk menambah __init.py!

Satu fail telah dijana mari teruskan.

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

Kami mentakrifkan pelayan dan menambah kelas ExcelService yang mengandungi kaedah yang dijana oleh fail proto. Kerana kami menerima fail mengikut bait perlu menggunakan pembaca bait io dan memulakan pemprosesan selanjutnya bagi fail dan populasi lajur kedua.

response = excel_pb2.FileResponse(file_content=output.read())

Pada akhirnya kami akan kembali ☝️ untuk pelanggan Go kami untuk menerima.

Untuk dapat mencari fail proto dalam python bagaimanapun anda harus menentukan laluan eksport

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

Menjalankan Pelanggan dan Pelayan

If all is good you can run

#First comes server

python3 -m main

#Then client

go run client.go Book1.xlsx

Dan anda harus mendapatkan fail .xlsx yang dikemas kini dalam bahagian klien Go.

Kesimpulan

Dalam artikel ini kami meneroka asas-asas menyediakan komunikasi gRPC antara pelayan Python dan klien Go. Dengan memanfaatkan gRPC, kami mewujudkan cara yang lancar untuk menghantar fail Excel daripada aplikasi Go ke pelayan Python, memproses fail menggunakan API GPT OpenAI dan mengembalikan fail yang diubah suai kembali kepada klien Go.

Atas ialah kandungan terperinci Komunikasi gRPC Antara Go dan Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn