Nanopb Protocol Buffers Generator
Nanopb is a small code-size Protocol Buffers implementation in ANSI C, primarily suitable for microcontrollers and other memory-restricted systems. The Python library component provides the `nanopb_generator.py` script, which compiles `.proto` definition files into C header (`.h`) and source (`.c`) files that can then be used with the Nanopb C runtime. The project is actively maintained, with versions typically released a few times a year, addressing bug fixes and minor improvements, such as the latest 0.4.9.1 release from December 2024.
Common errors
-
python: can't open file 'nanopb/generator/nanopb_generator.py': [Errno 2] No such file or directory
cause The generator script is not being called correctly. When installed via pip, it's typically a module within the Python path.fixUse `python -m nanopb.generator.nanopb_generator your_message.proto` instead of trying to run it directly as a file path. -
ImportError: No module named google.protobuf.text_format
cause The Python `protobuf` library (or `python-protobuf` on some systems) is not installed or not available in the active Python environment, which the Nanopb generator depends on.fixInstall the `protobuf` and `grpcio-tools` packages: `pip install protobuf grpcio-tools`. Ensure this is done for the Python environment you are using. -
protoc: command not found
cause The `protoc` executable, required by `nanopb_generator.py` for parsing .proto files, is not found in the system's PATH.fixInstall `grpcio-tools` via `pip install grpcio-tools` (which includes `protoc`), or manually install the Protocol Buffers compiler (`protoc`) and ensure its directory is in your system's PATH. -
Errors about missing file options.proto when running the generator
cause In nanopb 0.4.x, the transitional `options.proto` file was removed. If your `.proto` files imported it, they will fail to generate.fixChange any imports of `options.proto` in your `.proto` files to `import "nanopb/nanopb.proto";` (or `generator/proto/nanopb.proto` depending on context and generator options). -
FIELDINFO_DOES_NOT_FIT_widthX (static assertion error in generated C code)
cause This C compile-time error indicates that a message or field exceeds its allocated size, or the generator didn't correctly detect submessage sizes.fixProvide all `.proto` files as arguments to `nanopb_generator.py` simultaneously to ensure submessage definitions are found. Alternatively, use the `(nanopb).descriptorsize = DS_4` option, or manually set `max_size` and `max_count` options in `.options` files to correctly inform the generator.
Warnings
- breaking Python 2 support was officially removed in nanopb 0.4.x. The generator script now requires Python 3.
- gotcha The `nanopb_generator.py` script internally calls the `protoc` (Protocol Buffers compiler) executable. This means `protoc` must be installed and discoverable in your system's PATH, or provided by the `grpcio-tools` Python package.
- breaking Since nanopb 0.4.x, the `pb_common.c` file is always required by the C runtime library. Previously, it could be optionally excluded.
- breaking Default generator options changed in nanopb 0.4.x. `--no-timestamp` and `--no-strip-path` are now enabled by default, which affects the `#include` directives in the generated C files.
- gotcha The compatibility between `nanopb`'s generator and `protobuf` / `grpcio-tools` versions can sometimes be fragile due to API changes in `python-protobuf`.
Install
-
pip install nanopb -
pip install --upgrade protobuf grpcio-tools
Imports
- nanopb_generator.py (script)
import nanopb.generator
python -m nanopb.generator.nanopb_generator your_message.proto
Quickstart
# 1. Define your Protocol Buffer message in a .proto file (e.g., example.proto):
# message SimpleMessage {
# required int32 value = 1;
# }
# 2. Run the nanopb generator script:
import subprocess
import os
proto_content = """
syntax = "proto2";
message SimpleMessage {
required int32 value = 1;
}
"""
with open("example.proto", "w") as f:
f.write(proto_content)
# Ensure protobuf and grpcio-tools are installed
try:
import google.protobuf
print("google.protobuf module found.")
except ImportError:
print("google.protobuf not found. Please install with: pip install protobuf grpcio-tools")
exit(1)
# Specify the path to the generator script
# In an installed package, it's usually found via -m
generator_path = "nanopb.generator.nanopb_generator"
print(f"Generating C files from example.proto using {generator_path}...")
try:
# Using python -m for installed package
result = subprocess.run(
["python", "-m", generator_path, "example.proto"],
capture_output=True, text=True, check=True
)
print("STDOUT:", result.stdout)
print("STDERR:", result.stderr)
print("Successfully generated example.pb.h and example.pb.c")
# Verify output files exist (optional)
if os.path.exists("example.pb.h") and os.path.exists("example.pb.c"):
print("Output files example.pb.h and example.pb.c found.")
else:
print("Error: Generated files not found.")
except subprocess.CalledProcessError as e:
print(f"Error during generation: {e}")
print("STDOUT:", e.stdout)
print("STDERR:", e.stderr)
print("Make sure 'protoc' is available in your PATH or installed via grpcio-tools.")
except FileNotFoundError as e:
print(f"Error: Python or the generator script was not found. {e}")
# Clean up generated files
# os.remove("example.proto")
# if os.path.exists("example.pb.h"): os.remove("example.pb.h")
# if os.path.exists("example.pb.c"): os.remove("example.pb.c")