Python gRPC Protobuf 生成文件提示找不到模块
背景
最近学习抽空学习gRPC,准备为后面项目的需求提前做好预研,主要是Java与Python的交互,所以就打算使用gRPC来实现这个功能,在学习过程中遇到了这个问题,在此记录一下,避免过段时间就忘了。
项目结构
1 | pygrpc |
生成命令
1 | python -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. ./helloworld.proto |
1 | /home/charles/miniconda3/bin/conda run -n py_grpc --no-capture-output python /mnt/d/Program Files/JetBrains/PyCharm 2022.2.1/plugins/python/helpers/pydev/pydevd.py --multiprocess --qt-support=auto --client 127.0.0.1 --port 41177 --file /mnt/d/PycharmProjects/pygrpc/client/greeter_client.py |
报错分析
由于*_pb2_grpc.py
会使用*_pb2.py
中定义的各种类型,因此两者之间存在import
关系,而问题恰恰出在这个import
上。
注意我使用的指令:
*python -m
grpc_tools.protoc
--proto_path=.
--python_out=.
--grpc_python_out=.
helloworld.proto
中间的空格都被我给区分开了,上述指令的意思我们解读一下:
helloworld.proto
将所在目录为当前目录的``helloworld.proto`进行处理
--proto_path=.
将当前目录添加到搜索路径,用这个参数来寻找你proto
文件中的import
的文件路径
--python_out=.
生成的_pb2.py
存放于当前目录
--grpc_python_out=.
生成的_pb2_grpc.py
存放于当前目录
原因
在GitHub上找到了issue,问题在helloworld.proto
路径,同时也是执行目录的问题(./helloworld.proto
)。
Python下protoc
的解析方案是根据proto
文件的相对路径来确定导入路径的,也就是说,假如我的目录如下:
1 | pygrpc |
我如果想正确的编译,那么我应该在pygrpc
下使用
1 | python -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. example/helloworld.proto |
注意到指令末尾改为了相对路径example/helloworld.proto
,而--python_out
和--grpc_python_out
的目录相对于当前目录,执行完该指令后,protoc将会在--python_out
生成proto/helloworld_pb2.py
,在--grpc_python_out
下生成example/helloworld_pb2_grpc.py
,一般我们会将--python_out
和--grpc_python_out
指定为同一个目录。
再次展示我们的项目文件路径:
1 | │ main.py |