Pyaml-env: YAML with Environment Variable Resolution
Pyaml-env provides a straightforward way to parse YAML configuration files, automatically resolving environment variables denoted by the `!ENV` tag. It's built on top of PyYAML and is currently at version 1.2.2. The library maintains an active release cadence, with updates typically addressing bug fixes, dependency compatibility, and feature enhancements a few times a year.
Common errors
-
KeyError: 'MY_ENVIRONMENT_VARIABLE'
cause An `!ENV` tag was used for 'MY_ENVIRONMENT_VARIABLE' without a default value, and this environment variable was not set in the shell.fixEnsure the environment variable is set before running the application, or provide a default value in your YAML: `!ENV MY_ENVIRONMENT_VARIABLE:default_value`. -
yaml.scanner.ScannerError: while scanning a simple key
cause This error typically indicates a syntax error in your YAML file (e.g., incorrect indentation, missing colon, unquoted special characters).fixCarefully review the YAML file for syntax errors, paying close attention to indentation and character usage, especially around `!ENV` tags. -
TypeError: 'NoneType' object is not subscriptable
cause This often occurs when trying to access a nested key (e.g., `config['section']['key']`) but 'section' itself was resolved to `None` or was not found, leading to `config['section']` returning `None`.fixVerify that all intermediate keys exist in your YAML structure and resolve to mapping types. Ensure `!ENV` variables are correctly set or have defaults, preventing entire sections from becoming `None`.
Warnings
- breaking The default separator for environment variables and their default values changed from `|` to `:` in v1.1.0. If you were using `!ENV VAR|default_value`, it will now be interpreted incorrectly.
- gotcha When combining `!ENV` tags with explicit YAML type tags (e.g., `!!float`), the standard `!!float` syntax is not directly supported. You must use `tag:yaml.org,2002:datatype` instead.
- gotcha Prior to v1.2.0, pyaml-env would parse *any* environment variable, even if it was not explicitly marked with the `!ENV` tag. This could lead to unexpected behavior if an environment variable accidentally matched a YAML key.
- gotcha File encoding defaults to `utf-8` since v1.1.4. If you are using files with a different encoding, you might encounter `UnicodeDecodeError` or incorrect parsing.
Install
-
pip install pyaml-env
Imports
- parse_config
import pyaml_env; pyaml_env.parse_config(...)
from pyaml_env import parse_config
Quickstart
import os
from pyaml_env import parse_config
# Simulate setting environment variables
os.environ['API_KEY'] = 'your_secret_api_key'
os.environ['DEBUG_MODE'] = 'true'
os.environ['DB_PORT'] = '5432'
# Create a dummy YAML file for demonstration
config_content = """
api_config:
key: !ENV API_KEY
endpoint: https://api.example.com/v1
debug:
enabled: !ENV DEBUG_MODE:false # 'false' is default if DEBUG_MODE is not set
database:
host: localhost
port: !ENV DB_PORT:3306 # '3306' is default if DB_PORT is not set
user: !ENV DB_USER:default_user # 'default_user' is default if DB_USER is not set
logging:
level: INFO
"""
with open('config.yaml', 'w') as f:
f.write(config_content)
# Parse the configuration file
config = parse_config('config.yaml')
# Access resolved configuration values
print(f"API Key: {config['api_config']['key']}")
print(f"Debug Enabled: {config['debug']['enabled']} (type: {type(config['debug']['enabled'])})")
print(f"Database Port: {config['database']['port']} (type: {type(config['database']['port'])})")
print(f"Database User: {config['database']['user']}")
# Clean up the dummy file and environment variables
os.remove('config.yaml')
del os.environ['API_KEY']
del os.environ['DEBUG_MODE']
del os.environ['DB_PORT']
if 'DB_USER' in os.environ: # Only delete if it was actually set by this script or existed before
del os.environ['DB_USER']