PyYAML

raw JSON →
6.0.3 verified Tue May 12 auth: no python install: verified quickstart: verified

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.

pip install pyyaml
error YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated
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.
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)
error ModuleNotFoundError: No module named 'yaml'
cause The PyYAML library is not installed in the current Python environment or the script is attempting to import 'yaml' without it being available.
fix
Install the library using pip: pip install PyYAML
error yaml.scanner.ScannerError: while scanning a simple key
cause The YAML content being parsed contains a syntax error, commonly due to incorrect indentation, missing colons, or invalid characters.
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.
error yaml.representer.RepresenterError: cannot represent an object
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.
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.
breaking 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.
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().
breaking 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.
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.
gotcha 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.
fix Quote string values that look like booleans or octal numbers (e.g., 'NO', '0755'). Use explicit !!str tags if quoting is not possible.
gotcha yaml.safe_dump() escapes non-ASCII characters to \uXXXX by default, making UTF-8 content unreadable in the output file.
fix Pass allow_unicode=True to yaml.safe_dump() or yaml.dump() to emit UTF-8 characters directly.
gotcha 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.
fix Quote time-like strings explicitly, e.g. '"1:30"', or use a YAML 1.2-compliant library such as ruamel.yaml.
gotcha 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.
fix Consume the generator inside the 'with' block, or eagerly materialise it with list(yaml.safe_load_all(f)) before the block exits.
gotcha Tabs are not valid YAML indentation. Files indented with tabs instead of spaces raise a yaml.scanner.ScannerError that can be cryptic to diagnose.
fix Configure editors to expand tabs to spaces for .yaml/.yml files. Use a linter (yamllint) in CI to catch tab indentation early.
breaking 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.
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.
breaking 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.
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'.
pip install pyyaml libyaml
python os / libc status wheel install import disk
3.10 alpine (musl) - - 0.09s 19.9M
3.10 alpine (musl) - - - -
3.10 slim (glibc) - - 0.05s 21M
3.10 slim (glibc) - - - -
3.11 alpine (musl) - - 0.25s 21.9M
3.11 alpine (musl) - - - -
3.11 slim (glibc) - - 0.20s 23M
3.11 slim (glibc) - - - -
3.12 alpine (musl) - - 0.15s 13.8M
3.12 alpine (musl) - - - -
3.12 slim (glibc) - - 0.17s 15M
3.12 slim (glibc) - - - -
3.13 alpine (musl) - - 0.14s 13.5M
3.13 alpine (musl) - - - -
3.13 slim (glibc) - - 0.16s 15M
3.13 slim (glibc) - - - -
3.9 alpine (musl) - - 0.07s 19.4M
3.9 alpine (musl) - - - -
3.9 slim (glibc) - - 0.07s 21M
3.9 slim (glibc) - - - -

Round-trip: parse a YAML config string then dump it back to YAML text, with safe loader/dumper throughout.

import yaml

# --- Parse YAML (safe, no arbitrary code execution) ---
raw = """
service:
  host: localhost
  port: 8080
  debug: false
tags:
  - web
  - api
"""

config = yaml.safe_load(raw)
print(config['service']['host'])   # 'localhost'
print(config['service']['port'])   # 8080  (int, not str)
print(type(config['service']['debug']))  # <class 'bool'>

# --- Dump back to YAML text ---
output = yaml.safe_dump(config, allow_unicode=True, sort_keys=False)
print(output)

# --- Load multiple documents ---
multi = """
---
name: alpha
---
name: beta
"""
import io
docs = list(yaml.safe_load_all(io.StringIO(multi)))
print(docs)  # [{'name': 'alpha'}, {'name': 'beta'}]

# --- Error handling ---
try:
    yaml.safe_load("key: [unclosed")
except yaml.YAMLError as exc:
    print(f"Parse error: {exc}")