{"id":259,"library":"pyyaml","title":"PyYAML","description":"PyYAML is a YAML 1.1 parser and emitter for Python, providing safe and unsafe loaders, a complete Unicode-aware parser, pickle-compatible serialisation, and a capable extension API for custom tags and representers. Current version is 6.0.3 (released September 2025), which adds Python 3.14 and experimental free-threading support. The 6.x line follows an irregular maintenance cadence with patch releases typically spaced 1–2 years apart; a 7.0 dev branch exists but has no published release date.","status":"active","version":"6.0.3","language":"python","source_language":"en","source_url":"https://github.com/yaml/pyyaml","tags":["yaml","parser","serialization","configuration","markup","data-formats"],"install":[{"cmd":"pip install pyyaml","lang":"bash","label":"pip (pure Python + optional C extension)"},{"cmd":"pip install pyyaml libyaml","lang":"bash","label":"pip with explicit libyaml (faster C bindings)"}],"dependencies":[{"reason":"Optional C extension (LibYAML) that significantly speeds up parsing and emitting. PyYAML falls back to pure Python if not present.","package":"libyaml","optional":true}],"imports":[{"note":"The PyPI slug is 'pyyaml' but the Python package name is 'yaml'. Importing 'pyyaml' raises ModuleNotFoundError.","wrong":"import pyyaml","symbol":"yaml","correct":"import yaml"},{"note":"yaml.load() without a Loader raises TypeError in 6.0+; even with Loader=yaml.FullLoader it was vulnerable to RCE before 5.4. Always prefer safe_load() for untrusted input.","wrong":"yaml.load(stream)","symbol":"yaml.safe_load","correct":"import yaml\ndata = yaml.safe_load(stream)"},{"note":"safe_dump() does not accept a Dumper kwarg; use yaml.dump(data, Dumper=yaml.SafeDumper) if you need to pass one explicitly.","symbol":"yaml.safe_dump","correct":"import yaml\ntext = yaml.safe_dump(data, allow_unicode=True)"},{"note":"Base exception for all PyYAML parse and emit errors; catch this rather than bare Exception for YAML-specific error handling.","symbol":"yaml.YAMLError","correct":"from yaml import YAMLError"},{"note":"Returns a generator; the file/stream must remain open for the entire iteration. Consuming outside the 'with' block silently returns no documents.","symbol":"yaml.safe_load_all","correct":"import yaml\nfor doc in yaml.safe_load_all(stream): ..."}],"quickstart":{"code":"import yaml\n\n# --- Parse YAML (safe, no arbitrary code execution) ---\nraw = \"\"\"\nservice:\n  host: localhost\n  port: 8080\n  debug: false\ntags:\n  - web\n  - api\n\"\"\"\n\nconfig = yaml.safe_load(raw)\nprint(config['service']['host'])   # 'localhost'\nprint(config['service']['port'])   # 8080  (int, not str)\nprint(type(config['service']['debug']))  # <class 'bool'>\n\n# --- Dump back to YAML text ---\noutput = yaml.safe_dump(config, allow_unicode=True, sort_keys=False)\nprint(output)\n\n# --- Load multiple documents ---\nmulti = \"\"\"\n---\nname: alpha\n---\nname: beta\n\"\"\"\nimport io\ndocs = list(yaml.safe_load_all(io.StringIO(multi)))\nprint(docs)  # [{'name': 'alpha'}, {'name': 'beta'}]\n\n# --- Error handling ---\ntry:\n    yaml.safe_load(\"key: [unclosed\")\nexcept yaml.YAMLError as exc:\n    print(f\"Parse error: {exc}\")\n","lang":"python","description":"Round-trip: parse a YAML config string then dump it back to YAML text, with safe loader/dumper throughout."},"warnings":[{"fix":"Replace yaml.load(data) with yaml.safe_load(data) for plain data, or yaml.load(data, Loader=yaml.SafeLoader) if you must use load().","message":"yaml.load() now requires an explicit Loader argument. Calling yaml.load(data) without Loader raises TypeError in 6.0+. Previously it issued a DeprecationWarning (5.1–5.4) before becoming a hard error.","severity":"breaking","affected_versions":"<6.0"},{"fix":"Always use yaml.safe_load() or yaml.safe_load_all() for any input not fully controlled by the application. Never pass Loader=yaml.Loader (UnsafeLoader) on untrusted data.","message":"yaml.load() / yaml.full_load() with FullLoader were vulnerable to arbitrary code execution (CVE-2020-14343) on untrusted input in versions before 5.4. yaml.Loader (UnsafeLoader) remains dangerous in all versions.","severity":"breaking","affected_versions":"<5.4"},{"fix":"Quote string values that look like booleans or octal numbers (e.g., 'NO', '0755'). Use explicit !!str tags if quoting is not possible.","message":"PyYAML implements YAML 1.1, not YAML 1.2. Values like 'yes', 'no', 'on', 'off', 'true', 'false' (all case variants) are parsed as booleans. The two-letter country code 'NO' becomes Python False. Octal literals use the 0777 syntax (not 0o777). These differ from YAML 1.2 and JSON.","severity":"gotcha","affected_versions":"all"},{"fix":"Pass allow_unicode=True to yaml.safe_dump() or yaml.dump() to emit UTF-8 characters directly.","message":"yaml.safe_dump() escapes non-ASCII characters to \\uXXXX by default, making UTF-8 content unreadable in the output file.","severity":"gotcha","affected_versions":"all"},{"fix":"Quote time-like strings explicitly, e.g. '\"1:30\"', or use a YAML 1.2-compliant library such as ruamel.yaml.","message":"Sexagesimal (base-60) number parsing: a YAML 1.1 value like '1:30' is parsed as the integer 90, not a string. This silently corrupts time-string fields.","severity":"gotcha","affected_versions":"all"},{"fix":"Consume the generator inside the 'with' block, or eagerly materialise it with list(yaml.safe_load_all(f)) before the block exits.","message":"yaml.safe_load_all() returns a lazy generator. If the stream is closed before the generator is exhausted (e.g., outside a 'with' block), iteration silently yields nothing or raises an error.","severity":"gotcha","affected_versions":"all"},{"fix":"Configure editors to expand tabs to spaces for .yaml/.yml files. Use a linter (yamllint) in CI to catch tab indentation early.","message":"Tabs are not valid YAML indentation. Files indented with tabs instead of spaces raise a yaml.scanner.ScannerError that can be cryptic to diagnose.","severity":"gotcha","affected_versions":"all"},{"fix":"Ensure the libyaml development package (e.g., 'libyaml-dev' on Debian/Ubuntu, 'libyaml-devel' on RHEL/Fedora) is installed on the system before attempting to install PyYAML via pip.","message":"PyYAML's C extensions, which provide significant performance, require the libyaml C library to be present during installation. If libyaml is not installed on the system, pip may fail to find a suitable wheel or compile the extensions from source, leading to installation errors such as 'ERROR: Could not find a version that satisfies the requirement libyaml' or compilation failures.","severity":"breaking","affected_versions":"all"},{"fix":"Ensure the 'libyaml' development packages are installed in the system environment. For Alpine Linux, use 'apk add libyaml-dev'. For Debian/Ubuntu, use 'apt-get install libyaml-dev'. For Fedora/RHEL, use 'yum install libyaml-devel' or 'dnf install libyaml-devel'.","message":"PyYAML's installation can fail if the 'libyaml' C library development packages are not available in the system environment. This is especially true when a pre-built wheel is not available for the specific Python version and OS (e.g., musllinux/Alpine), forcing a source build that requires libyaml headers. The error 'ERROR: Could not find a version that satisfies the requirement libyaml' or 'No matching distribution found for libyaml' often points to this issue.","severity":"breaking","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-05-12T12:25:29.848Z","next_check":"2026-06-25T00:00:00.000Z","problems":[{"fix":"Explicitly specify a loader, typically `Loader=yaml.SafeLoader` for basic safe parsing or `Loader=yaml.FullLoader` for more features, to suppress the warning and enhance security: `data = yaml.load(yaml_file_content, Loader=yaml.SafeLoader)`","cause":"The `yaml.load()` function was called without explicitly specifying a `Loader` class, triggering a warning that the default `Loader` might be unsafe for untrusted input.","error":"YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated"},{"fix":"Install the library using pip: `pip install PyYAML`","cause":"The PyYAML library is not installed in the current Python environment or the script is attempting to import 'yaml' without it being available.","error":"ModuleNotFoundError: No module named 'yaml'"},{"fix":"Review and correct the YAML syntax in the file or string, ensuring proper indentation, valid key-value structure, and adherence to the YAML specification.","cause":"The YAML content being parsed contains a syntax error, commonly due to incorrect indentation, missing colons, or invalid characters.","error":"yaml.scanner.ScannerError: while scanning a simple key"},{"fix":"Define a custom representer for the specific object type using `yaml.add_representer()` to instruct PyYAML on how to serialize it, or convert the object to a standard Python type that PyYAML can handle before dumping.","cause":"PyYAML attempted to serialize a custom Python object (e.g., an instance of a user-defined class or certain built-in types like sets) for which it has no predefined rule (representer) on how to convert it to YAML.","error":"yaml.representer.RepresenterError: cannot represent an object"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.09,"mem_mb":1,"disk_size":"19.9M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":1,"disk_size":"21M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.25,"mem_mb":1.1,"disk_size":"21.9M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.2,"mem_mb":1.1,"disk_size":"23M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.15,"mem_mb":0.8,"disk_size":"13.8M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":0.8,"disk_size":"15M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":1,"disk_size":"13.5M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.16,"mem_mb":0.8,"disk_size":"15M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":1.1,"disk_size":"19.4M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":1.1,"disk_size":"21M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}