python-decouple

Strict separation of settings from code for Python apps, reading config from .env, .ini, or Docker secrets.

Library
PyPI
v3.8
3,038stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
46/100Fair
Development Activity0
Maintenance20
Community64
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
74/100Good
Architecture72
Code Quality78
Innovation55
Learning Curve90

python-decouple gives Python applications one small, dependency-light module for pulling configuration out of source code. Instead of hardcoding secrets and per-deploy values, or fighting with os.environ returning only strings, you call config('SECRET_KEY') and let decouple search environment variables, then a .env or settings.ini file, then an optional default — in that fixed precedence order.

It was built originally for Django projects but has no framework dependency; it works equally well in Flask, scripts, or any Python codebase that needs instance settings (database URLs, API keys, debug flags) kept out of version control. Casting support (including built-in Csv and Choices helpers) and a fail-fast UndefinedValueError for missing required values make misconfiguration surface immediately instead of silently defaulting to a truthy string.

What You Get

  • A pre-instantiated config object (AutoConfig) that auto-detects .env or settings.ini by walking up the directory tree from the caller’s module
  • Explicit Config + Repository classes (RepositoryEnv, RepositoryIni, RepositorySecret) for cases where you want to point at a specific file or Docker secrets directory instead of auto-detection
  • Type casting on read via the cast argument, including a dedicated boolean caster that correctly handles string values like 'False'
  • Built-in Csv helper for delimited list values with configurable delimiter, per-item cast, and post-processing into list/tuple/etc.
  • Built-in Choices helper for validating a value against an allowed set (flat list or Django-style choice tuples), raising on anything outside it
  • Fail-fast UndefinedValueError when a required key has no envvar, no file entry, and no default, instead of returning None silently

Common Use Cases

  • Django settings.py - load SECRET_KEY, DEBUG, DATABASE_URL, and email/host settings from a .env file instead of committing them, with cast=bool/cast=int for correct types
  • Twelve-factor deployments - keep the same codebase across dev/staging/prod by letting real environment variables override the checked-in .env/.ini defaults with no code change
  • Docker Swarm secrets - point RepositorySecret at /run/secrets/ so secret files mounted by the orchestrator are read the same way as any other config key
  • CI and script configuration - fail fast in CI when a required credential envvar is missing, rather than a script silently running with an empty or wrong value
  • Multi-environment Flask/Jupyter apps - explicitly construct Config(RepositoryEnv("path/to/.env")) when the auto-detected caller path isn’t where the .env file lives

Under The Hood

Architecture The whole library lives in one module, decouple.py, organized around a small set of cooperating classes rather than a layered framework: Config.get() is the single lookup path, checking os.environ first, then a pluggable Repository object (RepositoryEnv, RepositoryIni, RepositorySecret, or the no-op RepositoryEmpty), then an explicit default, raising UndefinedValueError when none apply. AutoConfig wraps this with lazy initialization: on first call it inspects sys._getframe() to find the caller’s file path, then walks parent directories via _find_file looking for settings.ini or .env, and instantiates the matching Repository before delegating to Config. Swapping the underlying Repository implementation (as RepositorySecret does for Docker secrets) is the only extension point, and nothing else in the call chain needs to change — a deliberately narrow design that keeps the ‘what breaks if this changes’ surface small.

Tech Stack Pure Python standard library — os, sys, string, shlex, io.open, and collections.OrderedDict — with configparser on Python 3 and a ConfigParser/SafeConfigParser compatibility shim for Python 2, guarded by a PYVERSION tuple check. There are zero runtime dependencies declared in setup.py; the package ships as a single py_modules=['decouple'] install. Test-only dependencies (mock, pytest, tox) are pinned in requirements.txt, and tox.ini runs the suite across a py2, py3 envlist, wired to Travis CI via .travis.yml.

Code Quality The tests/ directory has one file per repository type (test_env.py, test_ini.py, test_secrets.py, test_autoconfig.py) plus dedicated tests for the Csv and Choices helpers and the strtobool truth-value parser, using pytest with mock for filesystem/environment isolation — a thorough split for a single-file library. Error handling is explicit and typed: a custom UndefinedValueError exception, KeyError propagation from repository lookups, and ValueError from Choices on invalid values, rather than swallowing failures. There’s no static type-checking (no type hints, no mypy config) and no linter configuration beyond an .editorconfig, consistent with a small, stable, long-since-mature codebase.

What Makes It Unique The defining technical choice is the fixed three-tier precedence order — real environment variables always win over file-based config, which itself wins over an in-code default — combined with AutoConfig’s caller-path introspection so that from decouple import config; config('KEY') works with zero setup in the common case. Compared to plain os.environ access or hand-rolled .env parsing, decouple’s _cast_boolean explicitly special-cases the 'False'-is-truthy string trap, and the Csv/Choices helpers turn common but fiddly parsing (delimited lists, enum-like validation) into one-line casts. It intentionally stays a narrow, dependency-free utility rather than growing into a broader settings/config framework.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search