Skip to content

How to Manage Environment Variables in a Python Project

API keys and database credentials change between machines and environments; hardcoding them leaks secrets into version control. A .env file keeps these values outside the code, where each environment supplies its own.

Prerequisites

Create a .env file

Add a .env file to the project root with one KEY=value pair per line:

.env
DATABASE_URL=postgres://localhost:5432/mydb
SECRET_KEY=change-me-in-production
API_KEY=sk-test-abc123

Add .env to .gitignore

Warning

Add this line before the first commit that contains the .env file. Removing a file after it has been pushed does not erase it from Git history.

Open .gitignore and add:

.env

Projects created with uv init ship a .gitignore, but it does not include .env by default. For full .gitignore setup, see how to put your Python project on GitHub.

Load variables with uv run --env-file

uv’s --env-file flag injects variables into the process environment before Python starts. uv run executes the command inside the project’s virtual environmentAn isolated folder where Python installs packages for one project, keeping them separate from other projects and your system Python. Learn more → , ensuring all dependencies are installed first. Without --env-file, the script raises KeyError: 'DATABASE_URL' because no environment variable is set.

uv run --env-file .env python main.py
main.py
import os

database_url = os.environ["DATABASE_URL"]  # raises KeyError if missing
api_key = os.getenv("API_KEY", "fallback")  # returns "fallback" if missing

Pass --env-file multiple times to layer files (later files override earlier ones). Set UV_ENV_FILE=.env in the shell to avoid typing the flag on every invocation. If the shell and the .env file both define the same variable, the shell value wins.

Load variables with python-dotenv

When the project needs variables available at import time without passing a CLI flag, install python-dotenv:

uv add python-dotenv

Call load_dotenv() at the top of the entry point:

main.py
from dotenv import load_dotenv
import os

load_dotenv()  # reads .env; does not override variables already set in the shell

database_url = os.environ["DATABASE_URL"]

Document required variables with .env.example

Create a .env.example that lists every variable the project expects, with placeholder values:

.env.example
DATABASE_URL=postgres://user:password@localhost:5432/dbname
SECRET_KEY=change-me
API_KEY=your-api-key-here

Commit .env.example to version control. New contributors copy it to .env and fill in real values. Keep it updated when adding or removing variables.

Keep secrets away from AI coding agents

AI coding assistants read project files by default, including .env. Add .env to the agent’s ignore file (.claudeignore for Claude Code, .cursorignore for Cursor) to prevent it from reading secrets:

.claudeignore
.env

Learn More

Last updated on