pythonprotocol-buffersgrpcpython-importprotoc

How to get the import correct when creating protocol buffer?


I am relatively new to protocol buffers and python, so I stumbled upon a problem described below. (I've done plenty of research in this issue, but found no solution)

The relevant hirarchy of my code:

.
└── 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 is my starting point)

When I create the code from my protobuf with protoc, the files are placed correctly, as I want them to be. But the auto generated code inside of my 'foo_pb2_grpc.py' is not correct, precisly the import of 'foo_pb2.py'.

Actual state:

from protos import foo_pb2 as protos_dot_foo__pb2

Target state:

from ..protos import foo_pb2 as protos_dot_foo__pb2

I create the proto files via my 'create_python_proto.bat', command below:

setlocal

python -m grpc_tools.protoc -I . --python_out=.\client --grpc_python_out=.\client protos\foo.proto

endlocal

So when I run my program from 'main.py' I get an "ImportError" at 'foo_pb2_grpc.py' where it says:

"cannot import name 'foo_pb2' from 'protos' (unknown location)"

What am I doing wrong? I am desperatly searching for a solution, but I just cannot find one...

Thanks for helping me out in advance!

ps: both '_ _ init _ _.py' given in '.\MainFolder\client' and '.\MainFolder\client\protos' are empty


Solution

  • Although this seem undocumented from the protoc help you can define a mapping ${TARGET_PATH}=${PROTO_PATH} in the -I/--proto_path command line argument.

    The command line

    python -m grpc_tools.protoc -Iclient\protos=protos --python_out=. --grpc_python_out=. protos\foo.proto
    

    should give you valid python modules for your folder structure. With absolute imports from client.protos import foo_pb2 as ... instead of relative ones like mentioned in you target state.

    Compare basics tutorial: https://grpc.io/docs/languages/python/basics/#generating-grpc-interfaces-with-custom-package-path