YAMLOrderedDictLoader
This module provides a loader and a dumper for PyYAML, enabling the preservation of key order when loading YAML files into `collections.OrderedDict` objects and managing `OrderedDict` objects when dumping to YAML. It is built upon PyYAML and is currently marked as deprecated by its maintainers in favor of `Phynix/yamlloader`.
Common errors
-
AttributeError: module 'yamlordereddictloader' has no attribute 'CLoader'
cause `CLoader` is specific to the `Phynix/yamlloader` library, not `yamlordereddictloader`.fixIf you intend to use the C-accelerated loaders, you need to install and import from `Phynix/yamlloader` (e.g., `from yamlloader.ordereddict import CLoader`). If you are using `yamlordereddictloader`, use `Loader` or `SafeLoader` instead. -
YAML mapping order not preserved when using alias and yamlordereddictloader loader
cause Complex YAML structures involving aliases and merges can cause the `OrderedDict` from `yamlordereddictloader` to not retain the exact desired insertion order for merged content.fixThis often requires overriding the `flatten_mapping` method in a custom loader derived from `yamlordereddictloader.Loader` to precisely control how merged nodes are processed. A simpler fix might be to restructure the YAML or avoid aliases if explicit order is critical for merged blocks. -
yaml.representer.RepresenterError: cannot represent an object: <class 'collections.OrderedDict'>
cause This error typically occurs if you try to `yaml.dump` an `OrderedDict` without using `yamlordereddictloader.Dumper` or `SafeDumper` (or a custom representer). PyYAML's default Dumper doesn't know how to represent `OrderedDict` as a standard mapping while preserving order.fixEnsure you are passing `Dumper=yamlordereddictloader.Dumper` or `Dumper=yamlordereddictloader.SafeDumper` to your `yaml.dump()` calls. Also, ensure you have `from collections import OrderedDict` for creating the objects to dump.
Warnings
- breaking The `yamlordereddictloader` library is officially deprecated by its maintainer. It is recommended to migrate to the `Phynix/yamlloader` project, which offers an improved version with unit tests, performance enhancements (including C-implementation access), and active development.
- gotcha For Python 3.7+ and PyYAML 5.1+, standard Python dictionaries preserve insertion order by default. Additionally, PyYAML's `dump` function can accept `sort_keys=False` to prevent alphabetical sorting during dumping. This might reduce or eliminate the need for `yamlordereddictloader` in some use cases, especially for dumping. However, `yamlordereddictloader` explicitly uses `OrderedDict` for loading.
- gotcha Using `yaml.load()` without specifying `Loader=yamlordereddictloader.SafeLoader` can be a security risk. The default `yaml.UnsafeLoader` (or `yaml.FullLoader` in newer PyYAML versions) can construct arbitrary Python objects, potentially allowing an attacker to execute malicious code if they control the YAML input.
- gotcha When loading YAML with aliased objects, `yamlordereddictloader` might not preserve the mapping order as intuitively expected for merged items. Aliased objects might be placed 'too soon' in the resulting `OrderedDict`.
Install
-
pip install yamlordereddictloader
Imports
- Loader
from yamlordereddictloader import Loader
- SafeLoader
from yamlordereddictloader import SafeLoader
- Dumper
from yamlordereddictloader import Dumper
- SafeDumper
from yamlordereddictloader import CLoader
from yamlordereddictloader import SafeDumper
- OrderedDict
from collections import OrderedDict
Quickstart
import yaml
from collections import OrderedDict
from yamlordereddictloader import SafeLoader, SafeDumper
# Create a YAML string with a specific order
ordered_data_str = """
key_c: 3
key_a: 1
key_b: 2
inner_dict:
inner_b: 'val_b'
inner_a: 'val_a'
"""
# --- Loading YAML with preserved order ---
# Using SafeLoader for security
loaded_data = yaml.load(ordered_data_str, Loader=SafeLoader)
print("Loaded data (type: ", type(loaded_data), "):")
for key, value in loaded_data.items():
print(f" {key}: {value}")
assert isinstance(loaded_data, OrderedDict)
assert list(loaded_data.keys()) == ['key_c', 'key_a', 'key_b', 'inner_dict']
assert list(loaded_data['inner_dict'].keys()) == ['inner_b', 'inner_a']
print("\n--- Dumping data with preserved order ---")
# Create an OrderedDict to dump
data_to_dump = OrderedDict([
('name', 'Alice'),
('age', 30),
('details', OrderedDict([
('city', 'New York'),
('occupation', 'Engineer')
]))
])
# Using SafeDumper for security and default_flow_style=False for block style
dumped_yaml = yaml.dump(data_to_dump, Dumper=SafeDumper, default_flow_style=False)
print(dumped_yaml)
# Verify order after dumping and re-loading (optional, for testing)
re_loaded_data = yaml.load(dumped_yaml, Loader=SafeLoader)
assert list(re_loaded_data.keys()) == ['name', 'age', 'details']
assert list(re_loaded_data['details'].keys()) == ['city', 'occupation']