Arista Protobuf / Python gRPC bindings generator & library
Arista Protobuf / Python gRPC bindings generator & library (version 0.1.4). It provides tools to compile `.proto` files into Python classes, offering features like JSON serialization/deserialization, one-of support, and customized handling of Google Well-known Types. Forked from `python-betterproto`, it maintains compatibility with `grpclib` for async gRPC support. The project is actively maintained by Arista Networks, with development ongoing, though official PyPI releases have an irregular cadence.
Common errors
-
ModuleNotFoundError: No module named 'grpc_tools'
cause The `grpcio-tools` package, which contains the `grpc_tools.protoc` module for Python-based compilation, is not installed.fixInstall the `grpcio-tools` package: `pip install grpcio-tools`. Alternatively, ensure the full `aristaproto[compiler]` is installed: `pip install "aristaproto[compiler]"`. -
TypeError: 'Timestamp' object has no attribute 'tzinfo' (or similar datetime related errors)
cause `aristaproto` customizes `Timestamp` handling by subclassing Python's `datetime` to maintain nanosecond precision. Direct interactions expecting standard `datetime` behavior without considering this subclassing can lead to issues.fixWhen converting between `aristaproto.Timestamp` and standard `datetime` objects, be mindful of the subclassing. If you need a pure `datetime` object, explicitly convert it, but be aware of potential loss of nanosecond precision if not handled correctly. Refer to `aristaproto` documentation on `Timestamp` conversions. -
ERROR: Package 'aristaproto' requires a different Python: <4.0, >=3.9
cause You are attempting to install `aristaproto` on a Python version older than 3.9.fixUpgrade your Python environment to version 3.9 or newer. Consider using `pyenv` or `conda` for managing multiple Python versions.
Warnings
- breaking Python versions older than 3.9 are no longer supported. Attempting to install or run on older versions will fail.
- gotcha `aristaproto` is a fork of `python-betterproto`. While many concepts are similar, direct migrations may require adjustments due to renaming, specific behavior changes (e.g., Timestamp handling), and updated dependencies.
- gotcha The `aristaproto.serialized_on_wire()` function only supports checking if Proto 3 *message* fields were sent on the wire. It cannot be used to determine if *scalar* fields (like strings, integers) were explicitly sent or are just default values.
- gotcha When using the `--python_aristaproto_opt=pydantic_dataclasses` option for Pydantic model generation, you must explicitly install `pydantic` in your project. It is not included by default with `aristaproto`.
Install
-
pip install "aristaproto[compiler]" -
pip install aristaproto
Imports
- Message
import aristaproto from generated_proto_file import MyMessage class MyMessage(aristaproto.Message): ...
- which_one_of
import aristaproto field_name, value = aristaproto.which_one_of(message_instance, 'oneof_group_name')
- serialized_on_wire
import aristaproto if aristaproto.serialized_on_wire(message_instance.field_name): ...
Quickstart
# 1. Create a .proto file (e.g., example.proto)
# syntax = "proto3";
# package hello;
# message Greeting {
# string message = 1;
# }
# 2. Compile the .proto file (assuming 'example.proto' is in current dir)
# mkdir -p lib
# protoc -I . --python_aristaproto_out=lib example.proto
# OR using grpcio-tools (after pip install grpcio-tools):
# python -m grpc_tools.protoc -I . --python_aristaproto_out=lib example.proto
# 3. Use the generated code (e.g., from lib/hello/__init__.py)
import os
import sys
# Add the 'lib' directory to Python path if not already added
# In a real project, 'lib' would likely be part of your package structure
# or installed.
if os.path.exists('lib') and 'lib' not in sys.path:
sys.path.insert(0, 'lib')
from hello import Greeting
g = Greeting(message="Hello, Arista!")
print(f"Created message: {g.message}")
# Example of serialization
json_output = g.to_json()
print(f"JSON representation: {json_output}")
# Example of deserialization
g_from_json = Greeting.from_json(json_output)
print(f"Message from JSON: {g_from_json.message}")