PyYAML Environment Variable Tag
pyyaml-env-tag (current version 1.1) is a Python library that provides a custom YAML tag (!ENV) for referencing environment variables within YAML files. This allows for dynamic configuration and injecting sensitive data securely. It builds upon the PyYAML library. The project has seen recent releases in 2025, suggesting active maintenance, though official release cadence isn't explicitly stated beyond these updates.
Warnings
- gotcha Using `yaml.load()` (without specifying `Loader=`) is inherently unsafe, as it can parse arbitrary Python objects and potentially execute malicious code from untrusted YAML sources. This applies to `pyyaml-env-tag` as it extends PyYAML's loading capabilities.
- gotcha When using the sequence syntax for fallbacks (e.g., `!ENV [VAR1, VAR2, default]`), the *last* item in the sequence is always treated as a literal default value and will not itself be resolved as an environment variable name. It will be resolved to a Python object of its implied type (e.g., string, integer, boolean). If you intend `VAR2` to also be an environment variable name to be looked up, this behavior is correct. However, if the sequence only has two items like `!ENV [VAR1, VAR2]`, `VAR2` will be treated as the literal default, not as an environment variable name to resolve.
Install
-
pip install pyyaml-env-tag
Imports
- add_env_tag
from yaml_env_tag import add_env_tag
- construct_env_tag
from yaml_env_tag import construct_env_tag
Quickstart
import yaml
import os
from yaml_env_tag import add_env_tag
# Create a YAML string with environment variable tags
yaml_content = """
database:
host: !ENV DB_HOST
port: !ENV [DB_PORT, 5432] # Uses 5432 if DB_PORT is not set
user: !ENV [DB_USER, default_user] # Uses 'default_user' if DB_USER is not set
api_key: !ENV [API_KEY_SECRET, FALLBACK_API_KEY, "no_api_key_set"]
"""
# Set some environment variables for testing
os.environ['DB_HOST'] = 'localhost'
os.environ['API_KEY_SECRET'] = 'my_super_secret_key'
# DB_PORT, DB_USER, and FALLBACK_API_KEY are intentionally not set to demonstrate fallbacks
# Get a PyYAML SafeLoader and add the environment tag constructor to it.
# It's crucial to use SafeLoader for security with untrusted YAML.
SafeEnvLoader = add_env_tag(yaml.SafeLoader)
# Load the YAML content
config = yaml.load(yaml_content, Loader=SafeEnvLoader)
print("Loaded Configuration:")
print(config)
# Clean up environment variables (good practice, especially in automated tests)
del os.environ['DB_HOST']
del os.environ['API_KEY_SECRET']
# Expected output:
# Loaded Configuration:
# {
# 'database': {'host': 'localhost', 'port': 5432, 'user': 'default_user'},
# 'api_key': 'my_super_secret_key'
# }