PYTHON
Manage Layered Configurations with collections.ChainMap
Explore `collections.ChainMap` to combine multiple dictionaries into a single view, ideal for managing layered configurations, environment settings, and user preferences efficiently.
from collections import ChainMap
# Global configuration (lowest priority)
global_config = {
'DEBUG': False,
'LOG_LEVEL': 'INFO',
'DATABASE_URL': 'sqlite:///default.db',
'CACHE_ENABLED': True
}
# Environment-specific configuration (middle priority)
development_config = {
'DEBUG': True,
'LOG_LEVEL': 'DEBUG',
'DATABASE_URL': 'postgresql://dev_user:dev_pass@localhost:5432/dev_db',
}
# User-specific or runtime configuration (highest priority)
user_settings = {
'CACHE_ENABLED': False,
'THEME': 'dark'
}
# Combine configurations. The order matters: highest priority first.
app_config = ChainMap(user_settings, development_config, global_config)
print("--- Effective Application Configuration ---")
print(f"DEBUG: {app_config['DEBUG']}") # From development_config
print(f"LOG_LEVEL: {app_config['LOG_LEVEL']}") # From development_config
print(f"DATABASE_URL: {app_config['DATABASE_URL']}") # From development_config
print(f"CACHE_ENABLED: {app_config['CACHE_ENABLED']}") # From user_settings
print(f"THEME: {app_config['THEME']}") # From user_settings
print(f"UNDEFINED_KEY: {app_config.get('UNDEFINED_KEY', 'N/A')}") # Accessing non-existent key
# Demonstrate how ChainMap looks up
print("
--- Configuration layers ---")
print(f"Raw ChainMap: {app_config.maps}")
# Add a new temporary context
temporary_override = {'LOG_LEVEL': 'WARNING'}
with_override = app_config.new_child(temporary_override)
print(f"
LOG_LEVEL with temporary override: {with_override['LOG_LEVEL']}")
print(f"Original app_config LOG_LEVEL: {app_config['LOG_LEVEL']}")
How it works: `collections.ChainMap` provides a way to combine several dictionaries or other mappings into a single updatable view. When a key is looked up, it searches each mapping in the chain sequentially until it finds the key. Writes, however, only affect the first mapping in the chain. This makes `ChainMap` extremely useful for managing layered configurations (e.g., global defaults, environment-specific settings, and user overrides) or merging context objects in web applications, allowing for flexible and clean overrides without modifying the original dictionary layers. It's an efficient alternative to manually merging dictionaries.