{"id":6321,"library":"betterproto2","title":"Betterproto 2","description":"Betterproto2 is a fork of the original betterproto library, providing an improved experience for Protobuf and gRPC in modern Python environments. It generates readable, idiomatic Python code leveraging features like dataclasses, async/await, and type hinting. While currently in active development with a release cadence of minor versions, its documentation is still evolving, and the project is subject to breaking changes. It supports Protobuf 3 & gRPC code generation, with built-in binary and JSON serialization.","status":"active","version":"0.9.1","language":"en","source_language":"en","source_url":"https://github.com/betterproto/python-betterproto2","tags":["protobuf","grpc","serialization","code-generation","dataclasses","async"],"install":[{"cmd":"pip install betterproto2","lang":"bash","label":"Install core library"},{"cmd":"pip install \"betterproto2[compiler]\"","lang":"bash","label":"Install with compiler dependencies"}],"dependencies":[{"reason":"Required for execution.","package":"python","optional":false},{"reason":"Optional dependency for asynchronous gRPC client and server implementations. Automatically enabled for gRPC stub generation.","package":"grpclib","optional":true},{"reason":"Optional dependency for generating Pydantic models instead of standard dataclasses, enabled via a `--python_betterproto_opt=pydantic_dataclasses` flag during code generation.","package":"pydantic"},{"reason":"Optional, but commonly used for invoking the Protobuf compiler (`protoc`) if you don't have it installed globally.","package":"grpcio-tools","optional":true}],"imports":[{"note":"Generated Protobuf messages inherit from `betterproto.Message`.","symbol":"Message","correct":"import betterproto"},{"note":"Generated classes are imported from the Python files created by `protoc`.","symbol":"GeneratedMessage","correct":"from my_proto_package.my_proto_file import MyMessage"}],"quickstart":{"code":"# 1. Define your .proto file (e.g., example.proto)\n# syntax = \"proto3\";\n# package hello;\n# message Greeting {\n#   string message = 1;\n# }\n\nimport os\nimport subprocess\nimport sys\nfrom pathlib import Path\n\n# Create a dummy .proto file for demonstration\nproto_content = \"\"\"\nsyntax = \"proto3\";\npackage hello;\nmessage Greeting {\n  string message = 1;\n}\n\"\"\"\n\nproto_dir = Path(\"./temp_proto_gen\")\nproto_dir.mkdir(exist_ok=True)\nproto_file = proto_dir / \"example.proto\"\nproto_file.write_text(proto_content)\n\noutput_dir = Path(\"temp_betterproto_out\")\noutput_dir.mkdir(exist_ok=True)\n\n# 2. Generate Python code using protoc\ntry:\n    # Using grpcio_tools if available, otherwise direct protoc\n    if subprocess.run([sys.executable, '-m', 'grpc_tools.protoc', '--version'], capture_output=True, check=False).returncode == 0:\n        print(\"Using grpcio_tools.protoc\")\n        subprocess.run(\n            [\n                sys.executable,\n                '-m',\n                'grpc_tools.protoc',\n                f'-I={proto_dir}',\n                f'--python_betterproto_out={output_dir}',\n                str(proto_file)\n            ],\n            check=True\n        )\n    else:\n        print(\"Using system protoc (ensure it's installed)\")\n        subprocess.run(\n            [\n                'protoc',\n                f'-I={proto_dir}',\n                f'--python_betterproto_out={output_dir}',\n                str(proto_file)\n            ],\n            check=True\n        )\n    sys.path.insert(0, str(output_dir))\n    from temp_proto_gen.example import Greeting # Adjusted import based on package and file\n\n    # 3. Use the generated classes\n    greeting_instance = Greeting(message=\"Hello betterproto2!\")\n    print(f\"Created message: {greeting_instance}\")\n\n    # Serialize to bytes\n    serialized_data = bytes(greeting_instance)\n    print(f\"Serialized: {serialized_data}\")\n\n    # Deserialize from bytes\n    deserialized_instance = Greeting().parse(serialized_data)\n    print(f\"Deserialized: {deserialized_instance}\")\n\n    # Convert to dict and JSON\n    print(f\"To dict: {deserialized_instance.to_dict()}\")\n    print(f\"To JSON: {deserialized_instance.to_json(indent=2)}\")\n\nexcept Exception as e:\n    print(f\"Error during quickstart: {e}\")\n    print(\"Ensure 'protoc' is installed or 'pip install grpcio-tools'\")\nfinally:\n    # Clean up generated files and directories\n    import shutil\n    if proto_dir.exists():\n        shutil.rmtree(proto_dir)\n    if output_dir.exists():\n        shutil.rmtree(output_dir)\n    if str(output_dir) in sys.path:\n        sys.path.remove(str(output_dir))\n","lang":"python","description":"This quickstart demonstrates how to define a simple Protobuf message, generate Python code using `protoc` (either directly or via `grpcio-tools`), and then use the generated classes for message creation, serialization to binary and JSON, and deserialization. It cleans up temporary files after execution."},"warnings":[{"fix":"Refer to the betterproto2 documentation for updated API usage and migration guides. Expect manual adjustments to code.","message":"Betterproto2 is a redesign of the original betterproto library and is not a 1:1 drop-in replacement. While the wire format is identical, method names and call patterns have changed, requiring code updates for migration.","severity":"breaking","affected_versions":"All versions when migrating from original betterproto"},{"fix":"Regularly check the GitHub repository and release notes for updates. Pin dependency versions to avoid unexpected breaking changes.","message":"The project is still under active development, and the documentation is incomplete. Users should be aware that the library is still subject to breaking changes.","severity":"gotcha","affected_versions":"All current versions (0.9.1 and earlier)"},{"fix":"Install the official Protobuf compiler (`protoc`) for your platform, or add `grpcio-tools` to your project dependencies and invoke `python -m grpc_tools.protoc`.","message":"To generate Python code, you must have the `protoc` compiler installed and accessible in your PATH, or install `grpcio-tools` to use its bundled `protoc`. The `betterproto2[compiler]` extra installs necessary Python dependencies for the `protoc` plugin but not `protoc` itself.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use `betterproto.which_one_of(message, group_name)` to safely determine which field in a `oneof` group is set before attempting to access it.","message":"Accessing an unset `oneof` field now raises an `AttributeError`. Previously, it might have returned a default or `None` without an error.","severity":"breaking","affected_versions":"Potentially from betterproto 2.0.0b7 onwards, applies to betterproto2's design philosophy."},{"fix":"Avoid `isinstance(enum_member, enum.Enum)` checks. Adapt code to the new `Enum` behavior as defined by betterproto2, which aims for an 'open set' matching Protobuf's `Enum` behavior.","message":"Custom `Enum` implementations in betterproto2 do not behave like standard `enum.Enum` for `isinstance()` or `issubclass()` checks. This also affects direct passthrough of `Enum` members.","severity":"breaking","affected_versions":"Potentially from betterproto 2.0.0b7 onwards, applies to betterproto2's design philosophy."}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z"}