How to use environment variables with python-dotenv in Python
Storing passwords, API keys, or connection strings directly in your code is one of the most common — and most dangerous — mistakes in data projects. Environment variables solve the problem: they keep configuration out of the code, avoid exposing secrets, and make it easy to use different values on your laptop and on the server. In Python, the simplest way to work with environment variables is the python-dotenv library and a .env file.
Prerequisites
- Python 3.8 or later (check with
python --version). - A code editor, such as Visual Studio Code.
- Comfort using the terminal to install packages with
pip. - Ideally, a virtual environment created for the project.
Step 1: Install python-dotenv
The python-dotenv library reads .env files and makes those values available to your program. It is lightweight, has no external dependencies, and installs with a single command in the terminal:
pip install python-dotenv
If you work inside a virtual environment, activate it before installing so the package stays isolated from the rest of the system.
Step 2: Create the .env file
In the project root, create a file named .env — just the dot followed by the name, with no extension. Inside it, write one variable per line, in the format NAME=value, with no spaces around the equals sign:
DB_HOST=localhost
DB_USER=analytics
DB_PASSWORD=super-secreta-123
API_KEY=sk-exemplo-abcdef
By convention, names are written in uppercase. No quotes are needed: everything to the right of the equals sign is read as text.
Step 3: Protect the .env file
A secret is only safe if it never leaves your computer. If you use Git, add .env to your .gitignore file to make sure it is never pushed to the repository:
echo ".env" >> .gitignore
It is also good practice to create a .env.example file with the variable names but without the real values. That way, anyone who clones the project knows exactly which configuration they need to fill in.
Step 4: Load the variables in Python
With the file ready, it is time for the code. The load_dotenv() function looks for a .env file in the current folder and places each value into the process environment. From there, os.getenv() returns the value of each variable by name:
import os
from dotenv import load_dotenv
load_dotenv()
db_host = os.getenv("DB_HOST")
db_user = os.getenv("DB_USER")
api_key = os.getenv("API_KEY")
print(db_host, db_user)
Notice there is not a single password written in the code: all sensitive values live in the .env file. One important detail: by default, load_dotenv() does not override variables that are already set in the system. This is intentional, so that the server configuration always takes priority over the local file.
Step 5: Default values and avoiding errors
When a variable does not exist, os.getenv() returns None, which usually triggers an error later in the program. To prevent that, provide a default value as the second argument:
port = os.getenv("DB_PORT", "5432")
If the variable is mandatory, it is best to validate it right at startup and fail with a clear message, instead of letting the error surface later:
api_key = os.getenv("API_KEY")
if not api_key:
raise RuntimeError("API_KEY not found")
Check the result
Save the code in a file, for example config_teste.py, and run it in the terminal:
python config_teste.py
If you see the correct host and user printed, the read worked. You can also confirm the file was actually found, because load_dotenv() returns True when it successfully loads a .env and False otherwise. If the variables come back as None, the most common problem is that the .env file is not in the same folder from which you run the script — fix the path or pass the exact location to load_dotenv().
Conclusion
In five steps you separated configuration from code and stopped keeping secrets written in your scripts — an essential foundation for data projects that are secure and easy to move between environments. The next step is to use these variables in a real connection, such as to a SQL Server database or an API. Which secret will you take out of your code first: the database password or the API key?