念念不忘
必会回响

Python gRPC Protobuf 生成文件提示找不到模块

1. 背景

最近学习抽空学习gRPC,准备为后面项目的需求提前做好预研,主要是JavaPython的交互,所以就打算使用gRPC来实现这个功能,在学习过程中遇到了这个问题,在此记录一下,避免过段时间就忘了。

2. 项目结构

pygrpc
      client
          xxxclient.py
      example
             helloworld.proto
      server
          xxxserver.py

3. 生成命令

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

输出如下日志:

/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 
Connected to pydev debugger (build 223.8836.43)
Traceback (most recent call last):
  File "<frozen importlib._bootstrap>", line 1042, in _handle_fromlist
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/mnt/d/PycharmProjects/pygrpc/example/helloworld_pb2_grpc.py", line 5, in <module>
    import helloworld_pb2 as helloworld__pb2
ModuleNotFoundError: No module named 'helloworld_pb2'
ERROR conda.cli.main_run:execute(33): Subprocess for 'conda run ['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']' command failed.  (See above for error)

4. 报错分析

由于*_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存放于当前目录

5. 原因

在GitHub上找到了issue,问题在helloworld.proto路径,同时也是执行目录的问题(./helloworld.proto)。

Python下protoc的解析方案是根据proto文件的相对路径来确定导入路径的,也就是说,假如我的目录如下:

pygrpc
      client
          xxxclient.py
      example
             helloworld.proto
      server
          xxxserver.py

我如果想正确的编译,那么我应该在pygrpc下使用

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指定为同一个目录。

再次展示我们的项目文件路径:

│  main.py
│
├─client
│      greeter_client.py
│
├─example
│  │  helloworld.proto
│  │  helloworld_pb2.py
│  │  helloworld_pb2_grpc.py
│  │  __init__.py
│  │
│  └─__pycache__
│          helloworld_pb2.cpython-38.pyc
│          helloworld_pb2_grpc.cpython-38.pyc
│          __init__.cpython-38.pyc
│
└─server
        greeter_server.py
赞(8) 打赏
未经允许不得转载:堆上小栈 » Python gRPC Protobuf 生成文件提示找不到模块

评论 抢沙发

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册