Proper Python Configuration for Multi‑Environment Applications
This article explains how to structure Python projects so that configuration is managed through packages and environment variables, enabling seamless deployment across development, testing, staging, and production environments without code changes, while illustrating best practices with clear examples and code snippets.
The article discusses configuring Python applications that run in multiple environments (development, testing, production, etc.) using plain Python modules and packages rather than framework‑specific settings, emphasizing a clean, import‑time evaluation approach.
It begins with a brief overview of Python modules and packages, noting that a directory becomes a package when it contains an __init__.py file, and shows how large utility modules can be split into sub‑packages.
Although placing code in __init__.py is generally discouraged because it runs on import, the article demonstrates this by adding a sys.exit() call to illustrate side‑effects.
Next, it addresses the need for multiple environments and references the Twelve‑Factor App methodology, recommending that static configuration stay in code while dynamic or secret values live outside version control (e.g., as environment variables).
To switch environments, the author suggests using a single environment variable such as ENV (similar to RACK_ENV , RAILS_ENV , or NODE_ENV ) and outlines a simple convention:
common.py – shared configuration
environments/development.py – development‑specific overrides
environments/production.py, environments/staging.py – production‑specific overrides
The final goal is to import only the configuration package (e.g., import config ) and let the package decide which environment file to load.
Implementation details are shown using importlib :
import os, importlib
env = os.getenv('ENV', 'development')
module = importlib.import_module(f'environments.{env}')
globals().update(module.__dict__)This dynamic import loads the appropriate environment module at import time, merging its globals into the package namespace.
A real‑world example from the author’s own site demonstrates the directory layout, the contents of common.py , development.py , and production.py , and how a Redis manager obtains its configuration via RedisManager.from_config() , keeping the rest of the code agnostic of configuration details.
In conclusion, the method provides flexible, maintainable configuration for Python projects, supports unlimited environments, simplifies onboarding, isolates secrets, reduces CLI argument noise, and avoids external dependencies, all while using only standard Python features.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.