Install & Compatibility
Where this runs
tested against v0.6.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.910 runs
installs and imports cleanly · install 0.0s · import 0.135s · 20MB
glibcpy 3.10–3.910 runs
installs and imports cleanly · install 1.7s · import 0.129s · 21MB
18MB installed
● package 18MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
load
✓ from saneyaml import load
dump
✓ from saneyaml import dump
This quickstart demonstrates how to use `saneyaml.load` and `saneyaml.dump` to process YAML data. It highlights SaneYAML's core features: preserving order of keys and preventing implicit type conversions for values like 'yes', 'no', or date strings, which are often problematic in default PyYAML usage. Notice how 'No' and '2023-10-27' are loaded as strings, not booleans or datetime objects.
from saneyaml import load, dump
import io
# Example YAML data
config_data = {
'name': 'My App',
'version': '1.0.0',
'settings': {
'debug': 'No', # saneyaml keeps this as string, not bool
'log_level': 'INFO',
'features': ['alpha', 'beta']
},
'last_updated': '2023-10-27' # saneyaml keeps this as string, not datetime
}
# Dump to a YAML string (preserving order and types)
output_stream = io.StringIO()
dump(config_data, output_stream)
yaml_string = output_stream.getvalue()
print("\n--- Dumped YAML ---\n" + yaml_string)
# Load from a YAML string (preventing implicit conversions)
loaded_data = load(yaml_string)
print("\n--- Loaded Data ---")
print(f"Debug setting type: {type(loaded_data['settings']['debug'])} (value: {loaded_data['settings']['debug']})")
print(f"Last updated type: {type(loaded_data['last_updated'])} (value: {loaded_data['last_updated']})")
print(f"Loaded data equality: {loaded_data == config_data}")
# Demonstrate order preservation (requires Python 3.7+ for dicts)
# For older Pythons, saneyaml handles order internally.
original_keys = list(config_data.keys())
loaded_keys = list(loaded_data.keys())
print(f"Original top-level keys order: {original_keys}")
print(f"Loaded top-level keys order: {loaded_keys}")
Debug
Known issues
gotchaSaneYAML deliberately disables implicit type conversions for common string values like 'yes', 'no', 'on', 'off', dates, and some numbers. This means `yes` will be loaded as the string 'yes', not the boolean `True`. If you expect PyYAML's default 'smart' parsing, your code might receive `str` instead of `bool` or `datetime` objects.fixExplicitly convert loaded string values to the desired type in your application logic (e.g., `value == 'yes'` or `datetime.fromisoformat(value)`). This is the intended behavior of `saneyaml` to avoid surprises.
affects: All versions
gotchaWhile `saneyaml` preserves insertion order for mappings (dictionaries), if your application relies on PyYAML's advanced features like custom constructors/representers, anchors, or tags, `saneyaml` might not expose them directly or might override their behavior for safety. It prioritizes a simpler, more controlled YAML experience.fixFor complex YAML features or highly customized serialization, consider using `ruamel.yaml` or interacting directly with `PyYAML`'s `SafeLoader` and `SafeDumper` with custom configurations. `saneyaml` is best suited for straightforward configuration files.
affects: All versions
breakingPrior to Python 3.7, standard `dict` objects did not guarantee insertion order. `saneyaml` handles this internally to preserve order during dump/load. However, if mixing `saneyaml` with older Python versions and other YAML libraries, unexpected order behavior might occur due to underlying dictionary implementations.fixEnsure your environment uses Python 3.7 or newer for consistent dictionary order behavior. `saneyaml` itself has mechanisms to preserve order, but downstream processing with older Python dicts could lose it.
affects: < 0.5.0 (and Python < 3.7)
Errors
Common errors & fixes
saneyaml.parser.ParserError: while parsing a block mapping
This error, or a generic `YAMLError`, indicates malformed YAML input. Common causes include incorrect indentation, missing colons, or invalid syntax.
fixReview the YAML file or string for syntax errors. YAML is highly sensitive to indentation. Use an online YAML validator or a linter in your IDE to pinpoint issues.
AttributeError: 'module' object has no attribute 'CLoader'
This issue originates from the underlying `PyYAML` library and means it failed to load its C-based extensions, typically because the `libyaml` development headers are missing on your system.
fixInstall `libyaml` development headers on your operating system (e.g., `sudo apt-get install libyaml-dev` on Debian/Ubuntu, `brew install libyaml` on macOS, or `choco install libyaml` on Windows). Then, reinstall `PyYAML` using `pip install --force-reinstall PyYAML` to ensure it compiles with the C extensions.
ValueError: invalid literal for bool(): 'yes'
You are attempting to convert a string loaded by `saneyaml` (e.g., 'yes', 'no') directly to a boolean or another type, but `saneyaml` intentionally loads these as strings to prevent implicit conversions.
fixCompare the string value explicitly (e.g., `if loaded_data['key'] == 'yes':`). For other types like dates, use appropriate parsing functions (e.g., `datetime.fromisoformat(loaded_data['date_key'])`).
Upgrade
Version history
0.6.1latest on PyPI · released Aug 14, 2024
Audit
Dependencies
PyYAMLrequiredSaneYAML is a wrapper around PyYAML and requires it to function. It uses specific PyYAML loaders and dumpers for its 'sane' behavior.