Skip to main content
When developing applications that connect to database servers, email systems, or online APIs (like OpenAI or weather services), your code requires access credentials, such as API keys, passwords, or secret tokens. Hardcoding secrets directly into your source code is a major security risk. If you upload your code to GitHub, anyone can see and steal your credentials. The industry standard solution is to use Environment Variables stored inside a .env file.

1. What is a .env File?

A .env file is a plain text file placed in the root directory of your project. It stores configuration settings and secrets as key-value pairs.

Creating the .env File

Create a file named precisely .env (note the leading dot, and no file extension) in your project root:

2. Preventing Leaks with .gitignore

Because the .env file contains sensitive secrets, you must never upload it to GitHub. To ensure Git ignores this file, create a file named .gitignore in your project root and add the .env filename to it:

The Best Practice: .env.example

Since other developers need to know what environment variables your project requires to run, create a template file named .env.example containing only the variable names (with empty or placeholder values) and commit this file instead:

3. Loading Variables in Python

To load variables from the .env file into your Python program, we use the third-party library python-dotenv along with Python’s built-in os module.

Installation

Install the package using pip or uv:

Loading and Accessing in Code

Use load_dotenv() to read key-value pairs from .env and load them into Python’s environment variables. Then, retrieve them using os.getenv() or os.environ.get():

Practical Example: Secure API Call

Here is a practical example showing how to fetch weather data using an API key retrieved securely from environment variables:

Precautions & Best Practices

  1. Never Commit .env: Double-check that .env is listed inside .gitignore before making any git commits.
  2. Handle Missing Variables Gracefully: Always check if os.getenv() returns None for required credentials and raise descriptive configuration errors.
  3. Use Default Fallbacks: For non-sensitive settings (like ports, timeouts, or environment names), provide sensible fallback values:

Practice & Exercises

To reinforce what you’ve learned in this section (writing config keys, loading environment variables via python-dotenv, managing fallback defaults, and validating configuration keys), practice with these interactive notebooks:

Follow-Along Practice

Practice creating mock environment files, loading keys into execution memory, checking fallback parameters, and writing validation assertions to prevent missing environment exceptions.💻 VS Code | 🚀 Colab | 📥 Download

Practice Exercises

Test your knowledge with hands-on exercises on building automatic .env.example configuration templates, writing APP_ENV reload logic, and building multi-key configuration validators.💻 VS Code | 🚀 Colab | 📥 Download

What’s next?

Now that you have completed Extending Python (built-in modules, data handling, external packages, APIs, and secrets management), let’s move into Advanced Python, starting with Python Internals!

Python Internals

Learn about mutability, memory references, and reference counting