Python调用 gRPC (.NET库封装,WEB_API启动)
1、之前用过pythonnet方式,可以调用c#中的dll,但是如果是.net的库好像并不是那么兼容
2、之前也可以断电调试c#代码,但是后来怎么都调试不通了
so,换一种方式,AI TELL ME ,use a morden Method.

关于.proto
.proto 是 Protocol 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创建项目

第一次生成的好像不对,没有放这个:
<ItemGroup> <Protobuf Include="Protos\motion.proto" GrpcServices="Server" /> </ItemGroup>

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

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

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

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程序,可以看到:

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

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

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

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

一个单独的命令行下的测试客户端工具:
https://github.com/fullstorydev/grpcurl/releases/tag/v1.9.3
下载后:

在这里cmd进去,可以同grpcurl -help查看命名使用,也可以测试grpc接口
查看服务状态:
grpcurl -insecure localhost:7297 list

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


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

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

这一块就算是走通了,可以同API接口调用一些硬件封装的服务。
下面在Python中调用,毕竟Python脚本的灵活性,可以做更多有意思的事情。
Python 调用 gRPC 有两种方式:用 .proto 文件生成客户端代码 或 动态调用(grpc-tools / grpcio)。下面我给你最标准的方法。
1、先装python需要的库

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

执行:
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. motion1.proto
可以看到生成了2个.py文件:

然后创建一个脚本用来测试接口:
安装库:
python -m pip install grpcio
安装库的时候注意看是到哪个版本的python解释器下;
测试脚本如下:


关于这里的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端口,而不是https7297。
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; }); });

2、启动的时候选http

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

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

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

浙公网安备 33010602011771号