Skip to main content

Idiomatic Protocol Buffers for Python.

Project description

The Buf logo

protobuf-py

License PyPI version Slack

protobuf-py is a from-scratch Protobuf library for Python 3.10+.

100% Protobuf conformance with full support for proto2, proto3, and editions. Generated code is readable, typed, and works out of the box with no dependencies or extra tooling required. Native Rust module for high-performance encoding/decoding.

import copy
from gen.example_pb import User

user = User(
    first_name="Alice",
    last_name="Smith",
    active=True,
    locations=["NYC", "LDN"],
    projects={"atlas": "infra"},
)
wire = user.to_binary()
round_trip = User.from_binary(wire)
print(round_trip.to_json())
print(round_trip.has_field("first_name"))
updated = copy.replace(round_trip, active=False)  # Python 3.13+

How it compares

google-protobuf implements the full protobuf surface, but its Python API still carries Python-2-era patterns like SerializeToString(), HasField("x"), and WhichOneof("group"). Generated modules use opaque descriptor blobs and absolute imports, and that import behavior causes enough packaging pain that fix-protobuf-imports exists just to patch generated output.

betterproto improved ergonomics, but it remains proto3-only and does not cover core protobuf features like proto2, editions, and extensions. The original project now points to betterproto2, and that project still calls out active development, incomplete docs, and breaking changes.

protobuf-py is the only option that combines complete protobuf semantics with an idiomatic Python interface. You get typed generated classes, relative-import-friendly output, first-class oneof pattern matching, and modern copy semantics without extra runtime dependencies.

protobuf-py google-protobuf betterproto
Spec coverage ✅ Full (proto2, proto3, editions, extensions, custom options) ✅ Full ❌ Partial (proto3-only)
Type annotations ✅ Built-in ❌ Third-party tooling needed ✅ Built-in
Conformance tests ✅ 100% pass rate ⚠️ Contains known failures ❌ No conformance suite
Readable generated code ❌ Classes are built only at runtime and cannot be inspected
Imports ✅ Relative imports ❌ Broken without third-party tooling ✅ Relative imports
Oneofs ✅ Ergonomic, match-compatible ❌ String-returning WhichOneof() ⚠️ Tuple-returning helpers
Enums ✅ Python-native IntEnum int + EnumTypeWrapper ⚠️ Custom int subclass
Field presence msg.has_field("x") with IDE completions ⚠️ HasField("x") raises for proto3 scalars ⚠️ Helper-based
Field assignment (foo.x = 123) ✅ Direct assignment CopyFrom() required ✅ Direct assignment
copy.copy() / copy.replace()
Global mutable registry ✅ Explicit Registry ❌ Process-wide singleton behavior ✅ N/A
Zero dependencies ❌ Includes grpclib, python-dateutil, typing-extensions

Quickstart

// proto/user.proto
syntax = "proto3";

message User {
  string first_name = 1;
  string last_name = 2;
  bool active = 3;
}
# buf.gen.yaml
version: v2
inputs:
  - directory: proto
plugins:
  - local: protoc-gen-py
    out: src/gen
$ uv add protobuf-py
$ uv add --dev protoc-gen-py buf-bin
$ uv run -- buf generate

You now have a typed src/gen/user_pb.py you can import directly.

Generated code you can read

protoc-gen-py - protobuf-py's code generation plugin, - emits regular typed Python classes. See Getting started and Writing plugins for setup and configuration details.

_UserFields: TypeAlias = Literal["first_name", "last_name", "active", "manager", "locations", "projects"]

class User(Message[_UserFields]):
    __slots__ = ("first_name", "last_name", "active", "manager", "locations", "projects")

    if TYPE_CHECKING:
        def __init__(
            self,
            *,
            first_name: str = "",
            last_name: str = "",
            active: bool = False,
            manager: User | None = None,
            locations: list[str] | None = None,
            projects: dict[str, str] | None = None,
        ) -> None: ...

        first_name: str
        last_name: str
        active: bool
        manager: User | None
        locations: list[str]
        projects: dict[str, str]

Feature highlights

Typed oneofs with pattern matching

from protobuf import Oneof

match msg.result:
    case Oneof(field="value", value=v):
        handle_value(v)
    case Oneof(field="error", value=e):
        handle_error(e)

Well-known types with Python-friendly helpers

from datetime import UTC, datetime, timedelta
from protobuf.wkt import Any, Duration, Timestamp

ts = Timestamp.from_datetime(datetime.now(UTC))
td = Duration.from_timedelta(timedelta(minutes=5))
packed = Any.pack(user)

Container protocol for dynamic tools and reflection

for field in user:
    value = user[field]
    print(field.name, value)
    print(field in user)  # descriptor presence
    del user[field]
    user[field] = value

Project structure that behaves like Python

  • Generated files use relative imports.
  • Generated modules fit normal package layouts.
  • __init__.py files for generated package directories are created by default.

Migration

google-protobuf protobuf-py
msg.SerializeToString() msg.to_binary()
MessageType.FromString(data) MessageType.from_binary(data)
msg.HasField("nickname") msg.has_field("nickname")
msg.WhichOneof("result") + string checks match msg.result with typed Oneof
msg.Extensions[ext] msg[ext]
msg.child.CopyFrom(other) msg.child = other

Documentation

Packages

  • protobuf-py: The runtime library. Contains base types, generated well-known types, and serialization.
  • protoc-gen-py: The code generator plugin. Generates Python code that depends on protobuf-py.
  • protobuf-py-ext: The optional native extension for high performance. Used transparently when installed.

Native extension platform support

We currently publish protobuf-py-ext wheels for

  • Linux: arm64 / amd64 - glibc / musl
  • macOS: arm64
  • Windows: amd64 / arm64

protobuf-py includes a dependency on protobuf-py-ext for these platforms, meaning therea are no extra steps for you to use it.

Optimized wheels are published for the latest 3 versions of Python on Linux and MacOS, while other supported versions use the Python stable ABI, which will also work on unreleased Python versions and still has great performance.

We believe this covers almost all users, which is important because the native extension generally improves performance by an order of magnitude or two.

If you happen to be using an unsupported platform, feel free to file an issue so we can consider officially supporting it. In addition, you can easily build the extension for use on any other platform. Ensure Rust is installed and add protobuf-py-ext to your dependencies

$ uv add protobuf-py-ext

When your project is synced on a non-supported platform, Rust will automatically be invoked to build the extension package and it will be used with no other steps.

Compatibility

Python 3.10 and later versions are supported as long as they are maintained by CPython.

Versioning follows semantic versioning, with a major version increase accompanying breaking changes and other features introduced with minor version increases. Patch version increases only contain bugfixes. More details on what we consider breaking and not can be found in the FAQ.

Status: Pre-release

protobuf-py is not yet stable. The API may change before 1.0.

Legal

Offered under the Apache 2 license.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

protobuf_py-0.1.1.tar.gz (133.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

protobuf_py-0.1.1-py3-none-any.whl (181.7 kB view details)

Uploaded Python 3

File details

Details for the file protobuf_py-0.1.1.tar.gz.

File metadata

  • Download URL: protobuf_py-0.1.1.tar.gz
  • Upload date:
  • Size: 133.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for protobuf_py-0.1.1.tar.gz
Algorithm Hash digest
SHA256 6bd08ac4d8f1661965bbe2685429d79043704cdd1ee720a7a89617331742240b
MD5 3e2a3dee5156513938fb5650476a8083
BLAKE2b-256 72ed02fd902d9c51b7ff53dfc9a745eb11490722edfd30073af889e171f07b8e

See more details on using hashes here.

Provenance

The following attestation bundles were made for protobuf_py-0.1.1.tar.gz:

Publisher: release.yaml on bufbuild/protobuf-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file protobuf_py-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: protobuf_py-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 181.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for protobuf_py-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 efc4f50f275ed6dae10a1f30bb81ad1a75368557b3ff22a532b7a472050368f1
MD5 16549d98c108a14efd54fbb855842282
BLAKE2b-256 fd001b3775aca1c70e3007e06ef5996f6bb9b3a32341eb0cce3ffb6effad8dec

See more details on using hashes here.

Provenance

The following attestation bundles were made for protobuf_py-0.1.1-py3-none-any.whl:

Publisher: release.yaml on bufbuild/protobuf-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page