# You're designing the new dashboard locally ENABLE_NEW_DASHBOARD=true PAYMENT_PROVIDER=stripe_sandbox LOG_LEVEL=debug PyCharm, VSCode, or debugpy often require environment variables. Keep your personal debug port in .env.python.local :
# config.py from pathlib import Path from dotenv import load_dotenv import os BASE_DIR = Path( file ).resolve().parent Priority 1: The base .env (safe defaults, often committed) Use load_dotenv with override=False so it doesn't clobber existing OS env vars load_dotenv(BASE_DIR / ".env", override=False) Priority 2: .env.python (optional, for language-specific settings) load_dotenv(BASE_DIR / ".env.python", override=True) Priority 3: .env.python.local (HIGHEST priority, NEVER committed) This file should always override everything else. env_local_file = BASE_DIR / ".env.python.local" if env_local_file.exists(): load_dotenv(env_local_file, override=True) Now fetch your variables DATABASE_URL = os.getenv("DATABASE_URL") DEBUG = os.getenv("DEBUG", "False").lower() == "true" Step 3: The Git Configuration Ensure .env.python.local is never tracked. Update your .gitignore file: .env.python.local
In the modern Python development lifecycle, managing configuration secrets (API keys, database passwords, feature flags) is non-negotiable. Most developers are familiar with the standard .env file. But as your project scales from a solo script to a team-based application with staging, production, and local overrides, a new pattern emerges: .env.python.local . Update your
# Override only for performance testing DATABASE_URL=postgresql://user:pass@localhost:5432/perf_test DEBUG=True .env (committed): then only ignore *.local .
# .gitignore .env .env.python .env.python.local *.local Wait—why ignore .env as well? Because for maximum security, you should actually commit a .env.example file instead of the real .env . But if you choose to commit a safe .env (without secrets), then only ignore *.local . Let's look at concrete examples where this pattern saves the day. 1. Switching Between SQLite and Postgres Locally .env (committed):
ENABLE_NEW_DASHBOARD=false PAYMENT_PROVIDER=stripe_live