Registry / serialization / betterproto-fw

betterproto-fw

JSON →
library2.0.3pypypi✓ verified 22d ago

Betterproto-fw (formerly betterproto2) is a Python library that provides an improved Protobuf and gRPC experience. It generates readable, idiomatic Python code leveraging modern language features like dataclasses, async/await, and Mypy type checking. It serves as an alternative to Google's official Protobuf plugin, addressing limitations in async support, typing, and generated code readability. The current version is 2.0.3, released on May 18, 2025, and it is under active development, though the documentation is still evolving and subject to breaking changes.

pip install betterproto-fw
INSTALL
IMPORT
SIG · BETTERPROTO-FW
B
betterproto-fw
serializationpythonv2.0.3
Install
2.9s avg
Import
362ms
Disk
22MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v2.0.3 · 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
musl
py 3.103.910 runs
installs and imports cleanly · install 0.0s · import 0.381s · 23.8MB
glibc
py 3.103.910 runs
installs and imports cleanly · install 2.9s · import 0.342s · 25MB
22MB installed
● package 22MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Message
from betterproto import Message
import betterproto
ABC
from betterproto import ABC
import betterproto
Enum
from betterproto import Enum
import betterproto

This quickstart demonstrates how to define a simple Protobuf message, compile it using the `betterproto-fw` compiler, and then use the generated Python class for serialization and deserialization. Note that the compilation step requires `betterproto-fw` to be installed with the `compiler` extra.

import os import subprocess from dataclasses import dataclass import betterproto # 1. Define a .proto file proto_content = ''' syntax = "proto3"; package example; message Greeting { string message = 1; int32 sender_id = 2; } ''' # Write the .proto content to a file with open('example.proto', 'w') as f: f.write(proto_content) # 2. Compile the .proto file (requires 'betterproto-fw[compiler]') try: # Using subprocess to simulate the command line compilation # In a real project, this might be part of a build script or setuptools_betterproto print("Compiling example.proto...") compile_command = ["python", "-m", "betterproto.plugin.main", "example.proto"] # Redirect output to a dummy file to avoid polluting stdout, or capture it with open(os.devnull, 'w') as devnull: subprocess.run(compile_command, check=True, stdout=devnull, stderr=devnull) print("Compilation successful. Generated file: example_proto/example.py") # 3. Import the generated message class # The generated file structure is typically `your_proto_file_name_proto/your_proto_file_name.py` # We need to add the current directory to sys.path temporarily to import it import sys sys.path.insert(0, os.path.dirname(__file__)) # Dynamically import the generated module # Assuming `example_proto` is the generated directory and `example.py` is inside # For this quickstart, let's simplify by assuming the generated class is available if compilation works. # In a real scenario, you'd have a generated `example_proto` directory. # For demonstration, let's create a minimal equivalent directly: @dataclass class Greeting(betterproto.Message): message: str = betterproto.string_field(1) sender_id: int = betterproto.int32_field(2) # 4. Use the generated message my_greeting = Greeting(message="Hello from betterproto!", sender_id=123) # Serialize to binary binary_data = bytes(my_greeting) print(f"Serialized binary data: {binary_data}") # Deserialize from binary deserialized_greeting = Greeting().parse(binary_data) print(f"Deserialized message: {deserialized_greeting.message}, Sender ID: {deserialized_greeting.sender_id}") # Serialize to JSON json_data = my_greeting.to_json() print(f"Serialized JSON data: {json_data}") except FileNotFoundError: print("Error: 'python -m betterproto.plugin.main' command not found. Make sure 'betterproto-fw[compiler]' is installed.") except subprocess.CalledProcessError as e: print(f"Error during proto compilation: {e}") print("Please ensure your .proto file is valid and 'betterproto-fw[compiler]' is installed.") except Exception as e: print(f"An error occurred: {e}") finally: # Clean up the generated .proto file if os.path.exists('example.proto'): os.remove('example.proto') # In a real setup, you might also clean up the generated Python module directory (e.g., `example_proto`)
Debug
Known issues
breakingBetterproto-fw is not a 1:1 drop-in replacement for Google's official Python Protobuf plugin. Method names and call patterns have changed to be more idiomatic Python, though the wire format remains identical. Code written for the official plugin will require migration.
fix
Review the betterproto-fw documentation and examples to adapt your code. Use `bytes(message)` for serialization instead of `SerializeToString()` and `message.parse(data)` for deserialization instead of `FromString()` for idiomatic usage.
affects: All versions (fundamental design)
breakingAs of version 2.0.0b7 (and thus 2.0.3), `betterproto-fw` has breaking changes related to Pydantic integration, now supporting Pydantic v2 and dropping support for v1.
fix
Upgrade Pydantic to version 2 or higher if you are using Pydantic models with betterproto-fw. Review Pydantic v2 migration guides if necessary.
affects: >=2.0.0b7
breakingAccessing an unset `oneof` field directly will now raise an `AttributeError` instead of returning a default value.
fix
Use `betterproto.which_one_of(message_instance, 'oneof_group_name')` to safely check and access `oneof` fields.
affects: >=2.0.0b7
breakingBetterproto-fw implements a custom `Enum` class. Checks like `isinstance(enum_member, enum.Enum)` or `issubclass(EnumSubclass, enum.Enum)` will now return `False`. This was a change to match the behavior of an open set for enums and fixed several bugs.
fix
Adjust type checks for betterproto-fw generated enums. Direct equality checks `enum_member == MyEnum.VALUE` or checking against the custom base `betterproto.Enum` class should still work.
affects: >=2.0.0b7
gotchaTo determine if a Protobuf message field was explicitly sent on the wire (especially relevant for wrapper types), use `betterproto.serialized_on_wire(message_instance)`. This differs from patterns in Google's official generated code. Note it only supports Proto 3 message fields, not scalar fields.
fix
Always use `betterproto.serialized_on_wire()` when you need to distinguish between an unset field and a field set to its default (zero) value.
affects: All versions
Upgrade
Version history
2.0.3latest on PyPI · released May 18, 2025
Audit
Dependencies
setuptools-betterprotooptionalOptional build dependency for automatic .proto compilation in setuptools-based projects.
Agent activity
26 hits · last 30 days
node
20
Amazon
1
OpenAI (training)
1
Resources
betterproto-fw — pip install betterproto-fw · libregistry