{"id":7534,"library":"pyangbind","title":"PyangBind","description":"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.","status":"active","version":"0.8.7","language":"en","source_language":"en","source_url":"https://github.com/robshakir/pyangbind","tags":["yang","networking","network automation","data modeling","code generation","netconf","restconf"],"install":[{"cmd":"pip install pyangbind","lang":"bash","label":"Install PyangBind"}],"dependencies":[{"reason":"Core dependency for YANG parsing and plugin execution.","package":"pyang","optional":false},{"reason":"Used for XML serialization and deserialization.","package":"lxml","optional":false},{"reason":"Build-time dependency for packaging.","package":"setuptools","optional":false}],"imports":[{"note":"Base class for generated YANG objects.","symbol":"PybindBase","correct":"from pyangbind.lib.base import PybindBase"},{"note":"Utility to convert a PyangBind object to a Python dictionary (e.g., for JSON/YAML serialization).","symbol":"pybind_to_dict","correct":"from pyangbind.lib.serialise import pybind_to_dict"},{"note":"Type used for YANG 'decimal64' types to ensure precision.","symbol":"RestrictedPrecisionDecimal","correct":"from pyangbind.lib.yangtypes import RestrictedPrecisionDecimal"}],"quickstart":{"code":"import os\n\n# 1. Create a simple YANG model file (e.g., 'example.yang')\nyang_model_content = '''\nmodule example {\n  yang-version 1;\n  namespace \"urn:example:pyangbind:test\";\n  prefix \"ex\";\n\n  container config {\n    leaf hostname {\n      type string;\n      description \"Device hostname.\";\n    }\n    leaf-list interfaces {\n      type string;\n      description \"List of interfaces.\";\n    }\n  }\n}\n'''\nwith open('example.yang', 'w') as f:\n    f.write(yang_model_content)\n\n# 2. Generate Python bindings using pyang\n# This command is typically run from the command line, not Python.\n# For demonstration, we simulate it.\n# In a real scenario, you'd run: pyang -f pybind -o my_bindings.py example.yang\nimport subprocess\ntry:\n    subprocess.run(['pyang', '-f', 'pybind', '-o', 'my_bindings.py', 'example.yang'], check=True)\n    print(\"Bindings generated successfully to my_bindings.py\")\nexcept FileNotFoundError:\n    print(\"Error: 'pyang' command not found. Ensure pyangbind is installed correctly.\")\n    exit(1)\nexcept subprocess.CalledProcessError as e:\n    print(f\"Error generating bindings: {e}\")\n    print(e.stderr.decode())\n    exit(1)\n\n# 3. Use the generated Python classes\nimport my_bindings\nfrom pyangbind.lib.serialise import pybind_to_dict\n\n# Instantiate the top-level module class\n# The class name is typically derived from the YANG module name (e.g., 'example')\ninst = my_bindings.example()\n\n# Set values for the 'config' container and its leaves\ninst.config.hostname = \"my-device-1\"\ninst.config.interfaces.add(\"eth0\")\ninst.config.interfaces.add(\"eth1\")\n\n# Access and print values\nprint(f\"Hostname: {inst.config.hostname}\")\nprint(f\"Interfaces: {list(inst.config.interfaces)}\")\n\n# Serialize the object to a dictionary\ndata_dict = pybind_to_dict(inst)\nprint(\"\\nSerialized data:\")\nimport json\nprint(json.dumps(data_dict, indent=2))\n\n# Clean up generated files\nos.remove('example.yang')\nos.remove('my_bindings.py')\n","lang":"python","description":"This quickstart demonstrates how to define a simple YANG model, generate Python bindings using the `pyang` tool with the `pybind` plugin, and then interact with the generated Python classes to set data and serialize it to a dictionary."},"warnings":[{"fix":"Update any code interacting with YANG `binary` types to use the `YANGBinary` object directly or convert it as needed. If you have existing bindings, regenerate them with PyangBind 0.8.3+.","message":"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.","severity":"breaking","affected_versions":">=0.8.3"},{"fix":"Ensure your environment uses Python 3.7 or newer. Upgrade your Python installation if necessary.","message":"After PyangBind 0.8.0, Python 2 support was gradually phased out, and current versions (0.8.1+) officially require Python 3.7+.","severity":"breaking","affected_versions":">=0.8.1"},{"fix":"Always regenerate your Python bindings (`pyang -f pybind -o ...`) after upgrading `pyangbind` or when applying a fix that impacts generated code.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Avoid using Python reserved keywords as YANG identifiers where possible. If unavoidable, manually inspect generated Python code for `SyntaxError` and adjust either the YANG model or the generated code (if feasible and maintainable).","message":"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.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure `pyangbind` is installed correctly with its dependencies. Run `pip install pyangbind`.","cause":"The `pyang` dependency, which is essential for running the `pyang` command and the `pybind` plugin, is missing from your environment.","error":"ModuleNotFoundError: No module named 'pyang'"},{"fix":"Verify 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`).","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.","error":"AttributeError: 'Config' object has no attribute 'interface'"},{"fix":"Refactor 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`.","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.","error":"TypeError: 'YANGBinary' object cannot be interpreted as a buffer"},{"fix":"Rename the clashing identifier in your YANG model or implement a custom workaround in the generation process if the YANG model cannot be changed.","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.","error":"SyntaxError: invalid syntax (in generated_bindings.py)"}]}