Install & Compatibility
Where this runs
tested against v0.10.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.940 runs
installs and imports cleanly · install 0.0s · import 0.000s · 19.1MB
glibcpy 3.10–3.940 runs
installs and imports cleanly · install 2.0s · import 0.000s · 20MB
18MB installed
● package 18MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Message
✓ from betterproto2 import Message
✗ import betterproto
ABC
✓ from betterproto2 import ABC
✗ import betterproto
Casing
✓ from betterproto2 import Casing
✗ import betterproto
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.
# 1. Define your .proto file (e.g., example.proto)
# syntax = "proto3";
# package hello;
# message Greeting {
# string message = 1;
# }
import os
import subprocess
import sys
from pathlib import Path
# Create a dummy .proto file for demonstration
proto_content = """
syntax = "proto3";
package hello;
message Greeting {
string message = 1;
}
"""
proto_dir = Path("./temp_proto_gen")
proto_dir.mkdir(exist_ok=True)
proto_file = proto_dir / "example.proto"
proto_file.write_text(proto_content)
output_dir = Path("temp_betterproto_out")
output_dir.mkdir(exist_ok=True)
# 2. Generate Python code using protoc
try:
# Using grpcio_tools if available, otherwise direct protoc
if subprocess.run([sys.executable, '-m', 'grpc_tools.protoc', '--version'], capture_output=True, check=False).returncode == 0:
print("Using grpcio_tools.protoc")
subprocess.run(
[
sys.executable,
'-m',
'grpc_tools.protoc',
f'-I={proto_dir}',
f'--python_betterproto_out={output_dir}',
str(proto_file)
],
check=True
)
else:
print("Using system protoc (ensure it's installed)")
subprocess.run(
[
'protoc',
f'-I={proto_dir}',
f'--python_betterproto_out={output_dir}',
str(proto_file)
],
check=True
)
sys.path.insert(0, str(output_dir))
from temp_proto_gen.example import Greeting # Adjusted import based on package and file
# 3. Use the generated classes
greeting_instance = Greeting(message="Hello betterproto2!")
print(f"Created message: {greeting_instance}")
# Serialize to bytes
serialized_data = bytes(greeting_instance)
print(f"Serialized: {serialized_data}")
# Deserialize from bytes
deserialized_instance = Greeting().parse(serialized_data)
print(f"Deserialized: {deserialized_instance}")
# Convert to dict and JSON
print(f"To dict: {deserialized_instance.to_dict()}")
print(f"To JSON: {deserialized_instance.to_json(indent=2)}")
except Exception as e:
print(f"Error during quickstart: {e}")
print("Ensure 'protoc' is installed or 'pip install grpcio-tools'")
finally:
# Clean up generated files and directories
import shutil
if proto_dir.exists():
shutil.rmtree(proto_dir)
if output_dir.exists():
shutil.rmtree(output_dir)
if str(output_dir) in sys.path:
sys.path.remove(str(output_dir))
Debug
Known issues
breakingBetterproto2 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.fixRefer to the betterproto2 documentation for updated API usage and migration guides. Expect manual adjustments to code.
affects: All versions when migrating from original betterproto
gotchaThe project is still under active development, and the documentation is incomplete. Users should be aware that the library is still subject to breaking changes.fixRegularly check the GitHub repository and release notes for updates. Pin dependency versions to avoid unexpected breaking changes.
affects: All current versions (0.9.1 and earlier)
gotchaTo 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.fixInstall the official Protobuf compiler (`protoc`) for your platform, or add `grpcio-tools` to your project dependencies and invoke `python -m grpc_tools.protoc`.
affects: All versions
breakingAccessing an unset `oneof` field now raises an `AttributeError`. Previously, it might have returned a default or `None` without an error.fixUse `betterproto.which_one_of(message, group_name)` to safely determine which field in a `oneof` group is set before attempting to access it.
affects: Potentially from betterproto 2.0.0b7 onwards, applies to betterproto2's design philosophy.
breakingCustom `Enum` implementations in betterproto2 do not behave like standard `enum.Enum` for `isinstance()` or `issubclass()` checks. This also affects direct passthrough of `Enum` members.fixAvoid `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.
affects: Potentially from betterproto 2.0.0b7 onwards, applies to betterproto2's design philosophy.
Upgrade
Version history
0.10.0latest on PyPI · released May 10, 2026
Audit
Dependencies
pythonrequiredRequired for execution.
grpcliboptionalOptional dependency for asynchronous gRPC client and server implementations. Automatically enabled for gRPC stub generation.
pydanticrequiredOptional dependency for generating Pydantic models instead of standard dataclasses, enabled via a `--python_betterproto_opt=pydantic_dataclasses` flag during code generation.
grpcio-toolsoptionalOptional, but commonly used for invoking the Protobuf compiler (`protoc`) if you don't have it installed globally.