Introduction
Every Python application — whether a Django monolith, a FastAPI microservice, or a CLI tool — needs configuration. The Twelve-Factor App methodology prescribes storing configuration in environment variables, but raw os.getenv() calls with manual type coercions become unmaintainable quickly. The Python ecosystem has evolved four mature libraries that bring structure to configuration management: Pydantic Settings (type-validated, model-based), Dynaconf (multi-source, layered), python-decouple (lightweight, env-focused), and environs (marshmallow-powered, Flask-friendly).
This guide compares all four with realistic examples that go beyond “hello world” to show how production teams manage configuration across development, staging, and production.
Library Overview
| Feature | Pydantic Settings | Dynaconf | python-decouple | environs |
|---|---|---|---|---|
| GitHub Stars | 1,365 | 4,305 | 3,039 | 1,367 |
| Approach | Pydantic model with validation | Multi-source layered config | Simple .env + casting | Marshmallow schema-based |
| Type Validation | Full Pydantic validation | Type casting, validation hooks | Basic casting helpers | Marshmallow field types |
| Config Sources | .env, env vars, secrets | .env, .toml, .yaml, .json, .ini, Redis, Vault | .env, .ini | .env, env vars |
| Nested Config | Yes (nested models) | Yes (dotted keys) | No | Yes (prefix nesting) |
| Secrets Support | SecretsDir, AWS Secrets | Vault, Redis, custom loaders | No | No |
| Django Integration | Via pydantic-settings | Native django-dynaconf | Via django-decouple | Via env vars |
| Active Maintained | Yes (June 2026) | Yes (June 2026) | Moderate (Nov 2024) | Yes (June 2026) |
Pydantic Settings: Type-Validated Configuration Models
Pydantic Settings extends Pydantic’s data validation to application configuration. If you already use Pydantic for request/response schemas (FastAPI, Litestar, etc.), configuration models feel natural.
Installation:
| |
Basic Usage:
| |
Key advantages:
- Full Pydantic validation: Custom validators,
AfterValidator, discriminated unions — all Pydantic features work on config - Secret handling:
SecretStr/SecretBytesmask values inrepr()andmodel_dump() - Nested models: Group related configuration into sub-models for clean separation
- Computed fields: Derive config values from other settings with
@computed_field
Multi-environment example:
| |
Dynaconf: Multi-Source Layered Configuration
Dynaconf is the Swiss Army knife of Python configuration. It reads from .env, .toml, .yaml, .json, .ini, Redis, HashiCorp Vault, and more — all simultaneously, with a well-defined precedence order.
Installation:
| |
Basic Usage (config.py):
| |
settings.toml:
| |
Switching environments:
| |
External sources:
| |
Key advantages:
- Multi-format: TOML (recommended), YAML, JSON, INI, .env — all simultaneously
- Layered environments:
[default]→[development]→[local]→ env vars — predictable precedence - External backends: Redis, Vault, Consul, etcd for centralized configuration
- Django/Flask integration: Official extensions for both frameworks
- Validation hooks:
settings.validators.register()for runtime validation
python-decouple: Lightweight Env-Centric
python-decouple is the minimalist’s choice. It does one thing well: read configuration from .env files and environment variables with type casting — no models, no fancy backends, no dependencies beyond the standard library.
Installation:
| |
Basic Usage:
| |
.env file:
| |
.ini file support:
| |
| |
Key advantages:
- Zero learning curve:
config('KEY', default=val, cast=type)— that is the entire API - No dependencies: Pure Python standard library
- Django-friendly: Used by Django projects that outgrow
settings.pyhardcoding - Fast: Minimal overhead — just string reads and type casts
Key disadvantages:
- No nested config: Flat key-value only — no structured or hierarchical configuration
- No validation: Type casting is not validation —
config('PORT', cast=int)accepts negative numbers - Limited sources: Only
.envand.inifiles, no YAML/TOML/Vault
environs: Marshmallow Schema-Based
environs is built on top of Marshmallow, bringing schema-based configuration parsing with rich field types. It is particularly popular in the Flask ecosystem since it shares Marshmallow’s validation patterns.
Installation:
| |
Basic Usage:
| |
Schema-based (Marshmallow):
| |
Key advantages:
- Rich field parsers:
env.dj_db_url(),env.dj_email_url(),env.dj_cache_url()for Django-style URLs - Prefix grouping:
env.prefixed("DB_")naturally groups related settings - Marshmallow integration: Use full Marshmallow schemas for complex validation
- Flask-native: Pairs perfectly with Flask’s app factory pattern
Choosing the Right Configuration Library
Choose Pydantic Settings if:
- You already use Pydantic (FastAPI, Litestar, SQLModel, LangChain)
- You need strict type validation at startup (fail fast on bad config)
- You manage secrets with
SecretStrand want them masked in logs - Your configuration has nested structures (databases, caches, third-party APIs)
Choose Dynaconf if:
- You need to read from multiple sources (TOML for code, env vars for secrets, Redis for dynamic config)
- You manage multiple deployment environments with layered overrides
- You need centralized configuration via Redis or Vault
- You want Django/Flask drop-in integration
Choose python-decouple if:
- You need the simplest possible solution — one file, no dependencies
- Your configuration is flat (10–30 key-value pairs)
- You are working on a small to medium Django project
- You value minimalism and zero magic over features
Choose environs if:
- You use Flask and want Marshmallow-compatible validation
- You prefer prefix-based nested configuration
- You need Django-style URL parsers for databases, caches, and email backends
- Your team is comfortable with Marshmallow’s field patterns
Production Patterns
Pydantic Settings with multiple env files:
| |
Dynaconf with validation hooks:
| |
For related reading on configuration management, see our C++ Configuration Libraries guide which covers the same problem in the C++ ecosystem. For infrastructure-level configuration management, see our CMDB tools comparison. If you are managing secrets and credentials, our Secrets Configuration Management guide covers HashiCorp Vault alternatives.
FAQ
Which configuration library follows the Twelve-Factor App methodology best?
All four support environment variables as the primary configuration source. Pydantic Settings and Dynaconf are closest to the spirit of Twelve-Factor because they encourage a strict separation of config from code with validation. python-decouple is the most literal implementation — it is essentially a typed wrapper around env vars.
How do I handle secrets securely with these libraries?
Pydantic Settings uses SecretStr which masks values in repr(), str(), and model_dump(). Dynaconf supports HashiCorp Vault natively and can load .secrets.toml files excluded from version control. python-decouple and environs rely on .env files excluded via .gitignore. Never commit .env files with real credentials to version control.
Can I use multiple configuration sources simultaneously?
Dynaconf is designed for this — you combine TOML files, environment variables, and Redis/Vault with a configurable precedence order. Pydantic Settings can load multiple .env files with the env_file=(".env", ".env.local") pattern but does not natively support Redis or Vault.
Which library handles nested configuration best?
Pydantic Settings supports nested Pydantic models, letting you group DatabaseSettings, CacheSettings, and EmailSettings as sub-models with their own validation. Dynaconf supports nested keys via TOML sections and dotted key access. environs uses env.prefixed("DB_") for flat prefix grouping. python-decouple does not support nesting.
What about configuration reloading at runtime?
Dynaconf supports reloading: settings.reload() re-reads all sources. It also supports settings.configure(FORCE_DYNACONF_LOADING_FOR_TEST=true) for test overrides. The other three libraries load configuration once at startup — for runtime changes, you would need to implement a custom reload mechanism or restart the process.
How do I test code that depends on configuration?
All four libraries support test overrides. Pydantic Settings and Dynaconf support temporary overrides via context managers. python-decouple allows passing a custom RepositoryEnv pointing to a test .env file. environs supports creating an Env instance with no .env file and setting values directly. The Twelve-Factor recommendation is to pass config via environment variables in CI/CD pipelines.
💰 想测试你的市场判断力?我用 Polymarket 做预测市场交易——这是全球最大的预测市场平台,从大选结果到技术监管时间线,什么都可以押注。和赌博不同,这是真正的信息市场:你懂的信息越多,胜率越高。我靠预测技术相关事件的走向已经赚了不少。用我的邀请链接注册:Polymarket.com