Search code examples
python-3.xprotocol-buffersmypy

Mypy get attr-defined & name-defined error when use protobuf


I use protobuf in my code and generated a py file using the command: protoc --python_out=. samples/msg.proto, my proto file is:

syntax = "proto3";

message MsgPackage
{
  message Msg
  {
    uint32 code = 1;
    string msg = 2;
  }

  repeated Msg messages = 1;
}
Package Version
Python 3.11.2
mypy 1.0.1
protobuf 4.22.0

enter image description here

The Python protocol buffer compiler doesn’t generate data access code directly, it create type dynamic. So executing the type check by mypy will get some errors: enter image description here

How do I resolve the error like: Name "MsgPackage.Msg" is not defined

Thanks!


Solution

  • Please don't use images when copying-and-pasting text is trivial. Text is better than images because (a) it enables others to reuse your code; (b) will likely outlive the image.

    To answer your question, the reason is that you're not correctly using repeated fields.

    Here's a solution that uses repeated fields to both create and output a MsgPackage:

    from google.protobuf.internal.containers import RepeatedCompositeFieldContainer
    
    from msg_pb2 import MsgPackage
    
    
    # See print(type(m.messages) below
    def show_msg(msgs: RepeatedCompositeFieldContainer[MsgPackage.Msg]) -> None:
        print(msgs)
    
    
    # With Python, once you create the root Message, child messages
    # e.g. `MsgPackage.Msg` are constructed automatically
    m = MsgPackage()
    
    # In this case, because `messages` is a repeated field of type `Msg`
    # One (!) solution is to use `add` to add items
    # Another solution is to use `extend`
    x = m.messages.add()
    x.code = 5
    x.msg = "Hello"
    
    print(m)
    
    print(len(m.messages))
    
    # It's common to iterate over repeated fields
    for i in m.messages:
        print(f"{i.code}: {i.msg}")
    
    # RepeatedCompositeFieldContainer
    print(type(m.messages))
    
    show_msg(m.messages)
    

    See the Protobuf documentation for an explanation of how to use Python repeated fields.

    Here's the API documentation for google.protobuf.internal.containers

    NOTE You can generate PYI files using protoc too. These are often used by editors to provide type-checking of protoc-generated Python code:

    protoc --python_out=${PWD} --pyi_out=${PWD} msg.proto