I love gRPC, but I find every step of the protobuf process rather frustrating (particularly in Python). Even though they are structurally similar to data structures composed of lists and dicts, you can't really handle them that way.
- You can't assign a list to a repeated field or a dict to a message (also means you can't use iterators/comprehensions)
- You can't delete field attributes either (but you can
del msg.lst[:]
) - Unpopulated fields are not "falsey":
z.HasField('foo')
will be false butnot not z.foo
is True.
I could go on. Basically, it feels like the folks that wrote the Python implementation of protobuf either don't actually know how to write idiomatic python, or want to actively discourage devs from using protobufs as datastructures within a service and only use them at API boundaries. Which is really unfortunate since they are extremely handy for enforcing types and structures (I aggressively use mypy/hints/autocomplete, **kwargs
infuriates me). I've heard (haven't been able to find a source) that you aren't actually supposed to use protos dynamically this because of performance reasons, but I've also heard that Google does precisely this.
That leaves me with a few options:
- Deal with un-ergonomic protobuf interfaces, take the possible performance hit
- Use dicts and lists and parse them with
json_format
at ser/de boundaries (files, gRPC, etc) and lose static type checking - Parse at boundaries, but use stricter typed data objects. But now I have to maintain these data structures in lock step with the
.proto
files (I want to write a custom protoc generator but I don't have the time right now).
What's the best approach, given that I like to write rather structured python?
bounding_box
type with.slice
which lets you slice an array)