PyangBind
PyangBind is a plugin for `pyang` that converts YANG data models into a Python class hierarchy, enabling Python to manipulate data conforming to a YANG model. It facilitates programmatic interaction with network device configurations and operational state. The current version is 0.8.7, and releases are typically made a few times per year, often driven by bug fixes or new feature support.
Common errors
-
ModuleNotFoundError: No module named 'pyang'
cause The `pyang` dependency, which is essential for running the `pyang` command and the `pybind` plugin, is missing from your environment.fixEnsure `pyangbind` is installed correctly with its dependencies. Run `pip install pyangbind`. -
AttributeError: 'Config' object has no attribute 'interface'
cause You are trying to access a YANG element (container, leaf, list) that does not exist at the specified path in your generated Python object, or there's a typo in the attribute name.fixVerify the exact path and name of the YANG element in your YANG model and ensure it matches how you're accessing it in Python (e.g., `my_module.config.interface` vs `my_module.config.interfaces`). -
TypeError: 'YANGBinary' object cannot be interpreted as a buffer
cause Your code is trying to use a `YANGBinary` object (introduced in PyangBind 0.8.3+) as if it were the deprecated `bitarray` object or a raw byte string, which is incompatible.fixRefactor your code to correctly handle `pyangbind.lib.yangtypes.YANGBinary` objects. Use its methods or convert it to `bytes` if needed, rather than directly treating it as a `bitarray`. -
SyntaxError: invalid syntax (in generated_bindings.py)
cause A YANG identifier in your model (e.g., a leaf or container name) clashes with a Python reserved keyword (like `class`, `async`, `import`), leading to invalid Python syntax in the generated file.fixRename the clashing identifier in your YANG model or implement a custom workaround in the generation process if the YANG model cannot be changed.
Warnings
- breaking PyangBind 0.8.3 removed the `bitarray` dependency for the `binary` YANG type, replacing it with `pyangbind.lib.yangtypes.YANGBinary`. If you relied on `bitarray`'s API for binary data, your code will break.
- breaking After PyangBind 0.8.0, Python 2 support was gradually phased out, and current versions (0.8.1+) officially require Python 3.7+.
- gotcha Many bug fixes and feature additions (e.g., related to unique leaf-lists in 0.8.1, or `bits` type handling in 0.8.4/0.8.7) require regenerating your Python bindings for the changes to take effect. Simply upgrading the `pyangbind` library is not enough.
- gotcha YANG identifiers (module names, container names, leaf names) that clash with Python reserved keywords (e.g., `class`, `import`, `async`) can cause `SyntaxError` when generated. While `pyangbind` attempts to handle some cases by appending underscores (e.g., `async_`), it's not foolproof.
Install
-
pip install pyangbind
Imports
- PybindBase
from pyangbind.lib.base import PybindBase
- pybind_to_dict
from pyangbind.lib.serialise import pybind_to_dict
- RestrictedPrecisionDecimal
from pyangbind.lib.yangtypes import RestrictedPrecisionDecimal
Quickstart
import os
# 1. Create a simple YANG model file (e.g., 'example.yang')
yang_model_content = '''
module example {
yang-version 1;
namespace "urn:example:pyangbind:test";
prefix "ex";
container config {
leaf hostname {
type string;
description "Device hostname.";
}
leaf-list interfaces {
type string;
description "List of interfaces.";
}
}
}
'''
with open('example.yang', 'w') as f:
f.write(yang_model_content)
# 2. Generate Python bindings using pyang
# This command is typically run from the command line, not Python.
# For demonstration, we simulate it.
# In a real scenario, you'd run: pyang -f pybind -o my_bindings.py example.yang
import subprocess
try:
subprocess.run(['pyang', '-f', 'pybind', '-o', 'my_bindings.py', 'example.yang'], check=True)
print("Bindings generated successfully to my_bindings.py")
except FileNotFoundError:
print("Error: 'pyang' command not found. Ensure pyangbind is installed correctly.")
exit(1)
except subprocess.CalledProcessError as e:
print(f"Error generating bindings: {e}")
print(e.stderr.decode())
exit(1)
# 3. Use the generated Python classes
import my_bindings
from pyangbind.lib.serialise import pybind_to_dict
# Instantiate the top-level module class
# The class name is typically derived from the YANG module name (e.g., 'example')
inst = my_bindings.example()
# Set values for the 'config' container and its leaves
inst.config.hostname = "my-device-1"
inst.config.interfaces.add("eth0")
inst.config.interfaces.add("eth1")
# Access and print values
print(f"Hostname: {inst.config.hostname}")
print(f"Interfaces: {list(inst.config.interfaces)}")
# Serialize the object to a dictionary
data_dict = pybind_to_dict(inst)
print("\nSerialized data:")
import json
print(json.dumps(data_dict, indent=2))
# Clean up generated files
os.remove('example.yang')
os.remove('my_bindings.py')