藤蔓

Python调用 gRPC (.NET库封装,WEB_API启动)

1、之前用过pythonnet方式,可以调用c#中的dll,但是如果是.net的库好像并不是那么兼容

2、之前也可以断电调试c#代码,但是后来怎么都调试不通了

so,换一种方式,AI TELL ME ,use a morden Method.

image

 关于.proto

.protoProtocol Buffers(简称 Protobuf)定义文件,是 gRPC 用来定义接口和数据结构的描述文件
简单理解:

.proto 文件就是 跨语言的接口说明书 📄

它定义了:

  • 可以调用哪些 远程函数(RPC)

  • 函数的 输入参数

  • 函数的 返回值结构

然后工具会根据 .proto 自动生成不同语言的代码

语言生成文件
C# Service接口 + 数据类
Python 客户端调用代码
C++ 客户端/服务端
Java 客户端/服务端

所以:

motion.proto

会自动生成:

C# 服务端代码
Python 客户端代码

一、.proto 文件长什么样

例如你刚才用的:

syntax = "proto3";

package motion;

service MotionService {

  rpc MoveAbs (MoveAbsRequest) returns (Result);

}

message MoveAbsRequest {
  int32 pos = 1;
  int32 axis = 2;
}

message Result {
  bool ok = 1;
}

含义:

定义一个服务 MotionService
    ↓
里面有一个函数 MoveAbs
    ↓
输入 MoveAbsRequest
    ↓
返回 Result

二、gRPC 工作流程

motion.proto
      ↓
代码生成器
      ↓
-------------------------
C# Server代码
Python Client代码
-------------------------
      ↓
Python 调用 C#

所以 .proto接口的统一定义


三、为什么不用 JSON / HTTP?

gRPC 用 protobuf 的原因:

方式性能
JSON
XML 很慢
Protobuf ⭐⭐⭐⭐⭐

protobuf 优点:

  • 二进制格式

  • 数据体积小

  • 解析速度快

  • 跨语言

所以很多系统用:

gRPC + protobuf

例如:

  • Google 内部服务

  • Kubernetes

  • TensorFlow

  • 微服务架构


四、.proto 文件本质是什么

其实就是一种 IDL(Interface Definition Language)

类似:

C# interface

比如 C#:

public interface MotionService
{
    Result MoveAbs(int pos,int axis);
}

.proto 就是跨语言版本。


五、.proto 文件怎么创建

直接新建文本文件:

motion.proto

用 VSCode / VS 都可以。

语法高亮插件:

Protocol Buffers

六、生成代码的命令

Python:

python -m grpc_tools.protoc \
 -I ./proto \
 --python_out=. \
 --grpc_python_out=. \
 motion.proto

C#:

.csproj 会自动生成。


七、你可以把 .proto 理解成

接口协议

类似:

HTTP API 文档

但比 HTTP 更严格、更高效。


八、举个更贴近你项目的例子

你的 .proto 可以写成:

service MotionService {

  rpc Init (Empty) returns (Result);

  rpc MoveAbs (MoveAbsRequest) returns (Result);

  rpc MoveXY (MoveXYRequest) returns (Result);

  rpc GetAxisPos (AxisRequest) returns (AxisPosReply);

}

Python 就能调用:

motion.move_abs(10000,0)
motion.move_xy(200,300)
pos = motion.get_axis_pos(0)

九、一个很多人不知道但非常重要的点

.proto 文件是 整个系统最重要的文件

因为:

接口 = 系统契约

客户端和服务端都必须遵守。


如果你愿意,我可以再给你一套 专门针对运动控制的 .proto 设计模板`,里面会包含:

InitController
MoveAbs
MoveXY
MoveArc
Home
Stop
GetAxisPos
WaitDone
AlarmState

基本就是 工业视觉 + 运动控制系统标准接口设计

 

 

----------------------------------------------------开始创建一个项目-----------------------------------------------------------------

1、在终端中根据.proto创建项目

image

 第一次生成的好像不对,没有放这个:

<ItemGroup>
  <Protobuf Include="Protos\motion.proto" GrpcServices="Server" />
</ItemGroup>

image

重新生成:

这里改成Both可以生成客户端的代码,后面在WEB API的GET接口中调用grpc服务的接口,需要用到这个客户端的类。

image

 

生成的代码是在,这里,我是单独的一个grpc类库里面集成服务的:

image

 然后,把这个服务开起来,我是把它放到了一个WEBAPI项目中,作为引用,然后通过启动API的时候同时注册这个服务,并穷启动这个grpc服务,启动的代码如下:

image

using grpc.Motion1Server.Services;
using Motion1Server;
using MotionService;
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
//**add grpc server
builder.Services.AddGrpc();
builder.Services.AddGrpcReflection();   // ⭐⭐⭐ 必须有
//**
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

//AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
//**启动gRPC Server
app.MapGrpcService<MotionServiceImpl>();

if (app.Environment.IsDevelopment())
{
    app.MapGrpcReflectionService();  // 👈 加这个
}
//**
app.Run();

这样我启动这个API程序,可以看到:

image

 启动日志中有2个端口,是这样的原因:

image

 我的lannchSetting.json也是这样配置的

image

 测试,我通过默认的这个GET接口进入,代码如下,可以看到我用到了前面说的自动生成的客户端类。

image

 然后调用测试返回结果正确:

image

 

一个单独的命令行下的测试客户端工具:

https://github.com/fullstorydev/grpcurl/releases/tag/v1.9.3

下载后:

image

 在这里cmd进去,可以同grpcurl -help查看命名使用,也可以测试grpc接口

查看服务状态:

grpcurl -insecure localhost:7297 list

 

image

 调用一个grpc服务下的一个接口测试:

image

 

image

 调用一个加参数的接口测试:

image

 参数正确传递,返回了OK:

image

 这一块就算是走通了,可以同API接口调用一些硬件封装的服务。

下面在Python中调用,毕竟Python脚本的灵活性,可以做更多有意思的事情。

Python 调用 gRPC 有两种方式:.proto 文件生成客户端代码动态调用(grpc-tools / grpcio)。下面我给你最标准的方法。

1、先装python需要的库

image

pip install grpcio grpcio-tools

安装完成后,把之前c#那边的motion1.proto文件拷贝到这边python项目路径下:

image

 执行:

 python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. motion1.proto

可以看到生成了2个.py文件:

image

 然后创建一个脚本用来测试接口:

安装库:

python -m pip install grpcio

安装库的时候注意看是到哪个版本的python解释器下;

测试脚本如下:

image

 

image

 关于这里的AI解释及建议:

明白了,这个报错是在 Python 调用你的 gRPC 服务时发生的 TLS/SSL 验证失败

Ssl handshake failed (TSI_PROTOCOL_FAILURE): SSL_ERROR_SSL ... unable to get local issuer certificate

它说明 Python 客户端在尝试使用 HTTPS/TLS 连接 https://localhost:7297 时,无法验证你本地的自签名证书。


解决方案

1️⃣ 使用明文 HTTP(推荐本地调试)

既然你是本地测试,最简单的是在服务端和客户端都用 不加密的 HTTP/2

服务端(WebAPI):

你可以启用 HTTP/2 明文端口,例如已经看到你的日志:

http://localhost:5079

然后在 Python 客户端这样写:

import grpc
import motion1_pb2
import motion1_pb2_grpc

# 使用明文
channel = grpc.insecure_channel('localhost:5079')
client = motion1_pb2_grpc.MotionServiceStub(channel)

response = client.Init(motion1_pb2.Empty())
print(response.ok)

注意 insecure_channel 和使用 http 端口,而不是 https 7297。


2️⃣ 使用 TLS/HTTPS(如果必须)

如果你必须用 7297 的 HTTPS 端口:

  • Python 需要 信任你的自签名证书

  • 可以把证书路径传给 grpc.ssl_channel_credentials()

with open("path/to/your/localhost.crt", "rb") as f:
    trusted_certs = f.read()

creds = grpc.ssl_channel_credentials(root_certificates=trusted_certs)
channel = grpc.secure_channel('localhost:7297', creds)

但是一般本地调试,为了快速起步,直接用明文 insecure_channel 最方便。


✅ 建议

  • 本地调试:用 http://localhost:5079 + insecure_channel

  • 部署到生产:再配置 TLS + 证书。


我可以帮你写一个完整的 Python 本地调试调用示例,包括 Init()GetAxisPos(),直接用明文连接。

上面这些问题的解决:

1、WEB API启动grpc服务的programs.cs中,增加:

//配置 Kestrel 允许 HTTP/2 明文
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenLocalhost(5079, listenOptions =>
    {
        listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2;
    });
});

image

 2、启动的时候选http

image

 但是这个时候,swagger,没法用了,不过这个也只是为了开启grpc服务,不用也行,后面再研究配置,如果需要,就用https启动。

image

 接下来些python脚本测试,如下图两个接口测试调用OK:

image

 

那么接下来就需要完善下grpc服务代码,然后就可以愉快的在python这边玩起来了,python这边众多的科学计算、图形化的东西在调用接口后直接去做一些事情还是挺有意思的。

 

posted @ 2026-03-18 18:46  Matteo1  阅读(0)  评论(0)    收藏  举报
Anime Girl