My directory structure is as follows:
test
|-test.py
|-test.proto
|-test_pb2.py
|-__init__.py
|-comm
|-comm.proto
|-comm_pb2.py
|-__init__.py
both __init__.py is empty and test.proto is like this:
package test;
import "comm/comm.proto";
message Test{
optional comm.Foo foo = 1;
}
and comm.proto is like this:
package comm;
message Foo{}
i successfuly used command protoc --python_out=. -I. comm.proto in comm directory to compile comm.proto and protoc --python_out=. -I. test.proto in test directory to compile test.proto but when i tried to import test_pb2 in test.py, i encounter this error
TypeError: Couldn't build proto file into descriptor pool: Depends on file 'comm/comm.proto', but it has not been loaded
Can someone help me identify the reason and provide a solution, please?
So, I think how
protocworks with Python is more complicated|confusing than the average bear! My recourse is to use Golang to see what its SDK does and then reverse engineer that back into Python.The documentation says that
protocignores Protocol Buffers packages. See Defining your Protocol Format and the note:I'm unfamiliar with Python Packages and Modules but ...
package'sWhen you define a
packagein a proto file, convention is that the proto file be in a folder that matches thepackagename. You can see this with e.g. Google's Well-known Types and e.g.Timestamp. This is defined intimestamp.prototo be inpackage google.protobufand so it's in the a folder pathgoogle/protobufand, by convention, it's calledtimestamp.proto(though the file name is arbitrary).Because
message Testis inpackage testandmessage Foois inpackage comm, the structure would be more correctly (!?) structured as:When you use
protoc, you must define--proto_pathfor each distinct folder that containspackagefolders. In this case--proto_path=${PWD}which can be omitted.protocThis gives
protoc:Or, my preference is to be more emphatic and include the root (
${PWD}) of the protopackage's:Curiously, even though we were told that the
packagewould not have an effect on the Python code, it does. Thepackage testproto is output totestfolder andpackage commtocommfolder.You will need to create an empty
__init__.pyintest(but notcomm) for the code to work.MessageYour
comm.Foomessage is empty ({}) and so there's nothing to use.I tweaked it:
Yields:
protosfolderMy recommendation is to use a folder e.g.
protosto hold proto sources, i.e.And then e.g.:
This has the advantage of being more universally applicable if you decide to generate e.g. Golang sources too.