如何在创建协议缓冲区时正确导入



我对协议缓冲区和python相对陌生,所以我偶然发现了下面描述的问题。(我在这个问题上做了很多研究,但没有找到解决方案(

我的代码的相关层次:

.
└── MainFolder
├── main.py
├── create_python_proto.bat
├── protos
│   └── foo.proto
├── client
│   ├── protos
│   │   ├ __init__.py
│   │   ├ foo_pb2.py
│   │   └ foo_pb2_grpc.py
│   ├── __init__.py
│   ├── client.py
│   └── etc...
└── server
├── ...

(main.py是我的起点(

当我用protoc从protobuf创建代码时,文件被正确放置,就像我希望的那样。但是我的"foo_pb2_grpc.py"中自动生成的代码不正确,确切地说是导入了"foo_pb2.py"。

实际状态:

from protos import foo_pb2 as protos_dot_foo__pb2

目标状态:

from ..protos import foo_pb2 as protos_dot_foo__pb2

我通过下面的命令"create_python_proto.bat"创建proto文件:

setlocal
python -m grpc_tools.protoc -I . --python_out=.client --grpc_python_out=.client protosfoo.proto
endlocal

所以当我从"main.py"运行程序时;ImportError";在"foo_pb2_grpc.py"中显示:

"无法从"protos"(未知位置(导入名称"foo_pb2">

我做错了什么?我正在拼命寻找解决方案,但就是找不到。。。

谢谢你提前帮我!

ps:两个'_int_.py'都在'中给出。\MainFolder\client"one_answers"。\MainFolder\client\protos为空

根据我的经验,在protoc生成的Python中使用模块是困难的,最好避免。

gRPC repo的示例避免使用模块(可能是因为这个原因(。

一个解决方案是:

  • 创建一个真正的模块源,例如src
  • 手动修改foo_pb2_grpc.py导入路径
  • 使用绝对|相对import引用

使用:

src
├── client
│   ├── __init__.py
│   └── main.py
├── __init__.py
├── protos
│   ├── foo_pb2_grpc.py
│   ├── foo_pb2.py
│   └── __init__.py
└── server
├── __init__.py
└── main.py

和:

python 
-m grpc_tools.protoc 
--proto_path ${PWD}/protos 
--python_out=${PWD}/src/protos 
--grpc_python_out=${PWD}/src/protos 
${PWD}/protos/foo.proto

src/protos/foo_pb2_grpc.py:

from ..protos import foo_pb2 as foo__pb2

或者:

import src.protos.foo_pb2 as foo__pb2

例如src/server/main.py:

from ..protos import foo_pb2
from ..protos import foo_pb2_grpc

from src.protos import ...

注意protoc生成的包表示对等端(客户端|服务器(之间的接口。如果这些文件由第三方提供,则生成的文件将位于一个完全不同的模块(com.third.party(中。对于内部原型,您可能希望遵循类似的做法。至少,将它们放在它们的客户端和服务器实现旁边(此处为src.protos(。

最新更新