Working with Environment Variables in Python
Environment variables are key-value pairs that live outside your Python code. They let you configure your application without changing source code. This is essential for different environments—development, testing, production—where you need different settings.
Why Environment Variables Matter
When you deploy an application, you rarely want hardcoded values. Database passwords, API keys, and feature flags should live outside your code. Environment variables solve this problem elegantly.
They are:
- Secure — Secrets stay out of your source code
- Flexible — Change behavior without redeploying code
- Portable — Work across operating systems
- Standard — Used by virtually every programming language and deployment tool
Reading Environment Variables
Python provides the os module for working with environment variables:
import os
# Read an environment variable
db_host = os.environ.get("DB_HOST")
print(db_host) # None if not set
# Provide a default value
debug_mode = os.environ.get("DEBUG", "false")
print(debug_mode) # "false" if DEBUG is not set
The get() method returns None if the variable does not exist. Providing a default avoids crashes and lets your code handle missing variables gracefully.
Setting Environment Variables
You can also set environment variables from within Python:
import os
os.environ["MY_APP_VERSION"] = "1.2.3"
print(os.environ.get("MY_APP_VERSION")) # 1.2.3
These changes affect the current process and any child processes it spawns. They do not modify the system’s permanent environment.
Working with os.environ
The os.environ object behaves like a dictionary:
import os
# Check if a variable exists
if "API_KEY" in os.environ:
api_key = os.environ["API_KEY"]
# List all environment variables
for key, value in os.environ.items():
print(f"{key}: {value}")
# Delete a variable
del os.environ["TEMP_VAR"]
# Or use:
os.environ.pop("TEMP_VAR", None)
Be careful when accessing keys directly with os.environ[key]—it raises a KeyError if the variable does not exist. Use get() for safer access.
The os Module vs os.environ
Both os.environ and os.environ.get() work, but there is a subtle difference. os.environ is a dict-like object, while os.environ.get() is a method on that object:
import os
# These are equivalent:
value1 = os.environ.get("MY_VAR")
value2 = os.environ.get("MY_VAR")
# Both return None when not found
Use whichever feels more natural in your code.
Real-World Examples
Database Configuration
import os
DB_HOST = os.environ.get("DB_HOST", "localhost")
DB_PORT = os.environ.get("DB_PORT", "5432")
DB_NAME = os.environ.get("DB_NAME", "mydb")
DB_USER = os.environ.get("DB_USER", "admin")
DB_PASSWORD = os.environ.get("DB_PASSWORD", "")
# Connect using these values
connection_string = f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
Feature Flags
import os
def is_feature_enabled(feature_name):
"""Check if a feature flag is enabled."""
return os.environ.get(f"FEATURE_{feature_name.upper()}", "false").lower() == "true"
if is_feature_enabled("new_dashboard"):
show_new_dashboard()
else:
show_old_dashboard()
Application Mode
import os
APP_ENV = os.environ.get("APP_ENV", "development")
DEBUG = APP_ENV == "development"
if DEBUG:
print("Running in development mode")
else:
print("Running in production mode")
Best Practices
Keep these tips in mind when working with environment variables:
Use descriptive names. Prefix your variables with your app name to avoid collisions: MYAPP_DATABASE_URL instead of DATABASE_URL.
Provide sensible defaults. Your application should work with minimal configuration, even if some features are disabled.
Validate early. Check for required variables at startup and fail fast with clear error messages:
import os
required_vars = ["DATABASE_URL", "API_KEY"]
missing = [v for v in required_vars if not os.environ.get(v)]
if missing:
raise RuntimeError(f"Missing required environment variables: {missing}")
Do not log sensitive values. Never print or log passwords, API keys, or tokens.
Use a .env file for local development. The python-dotenv package loads variables from a .env file:
# pip install python-dotenv
from dotenv import load_dotenv
load_dotenv() # Loads .env file in current directory
This keeps local development simple without polluting your shell environment.
See Also
- os-module — Full reference for the os module
- sys-module — System-specific parameters and functions
- pathlib-module — Path handling for file operations