> ## Documentation Index
> Fetch the complete documentation index at: https://fastapi2day.codewithsiva.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Python .env Files: Managing Secrets and Config Safely

> Protect API keys and credentials by storing them in .env files and loading them with python-dotenv — the industry standard approach.

Every real-world application needs configuration: API keys, database URLs, secret keys, debug flags, port numbers. Hardcoding these values directly in your source code is a security risk — they may end up committed to a public Git repository, visible to every developer, or wrong for a different deployment environment. The industry-standard solution is **environment variables**, and the most convenient way to manage them during development is a **`.env` file** loaded with **python-dotenv**.

## Why You Need Environment Variables

Consider a naive approach:

```python theme={null}
# ❌ Never do this
API_KEY = "sk-1234567890abcdef"
DATABASE_URL = "sqlite:///myapp.db"
DEBUG = True
```

This approach has serious problems:

* Secrets are embedded directly in your source code.
* They will be committed to Git and potentially exposed publicly.
* Every developer working on the project has to edit the source file.
* Production, staging, and development environments all need different values.

The solution is to read these values from **environment variables** instead:

```python theme={null}
import os

api_key = os.environ.get("API_KEY")
```

Your code simply asks the operating system for the value — it never hard-codes where that value comes from.

## What is a `.env` File?

A `.env` file is a plain text file that stores environment variables as `KEY=VALUE` pairs, one per line:

```text theme={null}
# .env

API_KEY=sk-1234567890abcdef
DATABASE_URL=sqlite:///myapp.db
DEBUG=True
PORT=8000
```

Instead of typing multiple `export` commands in every terminal session, you write the variables once in this file.

## Setting Up python-dotenv

Install the package:

```bash theme={null}
pip install python-dotenv
```

Call `load_dotenv()` at the very beginning of your application — before you read any environment variables:

```python theme={null}
from dotenv import load_dotenv
import os

load_dotenv()

api_key     = os.environ.get("API_KEY")
database    = os.environ.get("DATABASE_URL")
debug       = os.environ.get("DEBUG")
port        = os.environ.get("PORT")

print(api_key)    # sk-1234567890abcdef
print(port)       # 8000
```

After `load_dotenv()` runs, every variable from `.env` behaves exactly like a regular OS environment variable.

## Safe Variable Access

Prefer `os.environ.get()` over `os.environ[]`. The `get()` method returns `None` when a variable is missing rather than raising a `KeyError`. You can also supply a fallback default:

```python theme={null}
# ✅ Safe — returns None if PORT is not set
port = os.environ.get("PORT")

# ✅ Even better — provides a sensible default
port = os.environ.get("PORT", "8000")
```

## Complete Example

**`.env`**

```text theme={null}
OPENAI_API_KEY=sk-your-key
MODEL=gpt-4.1
MAX_TOKENS=200
```

**`app.py`**

```python theme={null}
from dotenv import load_dotenv
import os

load_dotenv()

API_KEY    = os.environ.get("OPENAI_API_KEY")
MODEL      = os.environ.get("MODEL")
MAX_TOKENS = os.environ.get("MAX_TOKENS")

print(API_KEY)
print(MODEL)
print(MAX_TOKENS)
```

## Project Structure

```text theme={null}
project/
│
├── .env            ← your actual secrets (never commit this)
├── .env.example    ← safe template to share with teammates
├── .gitignore
├── app.py
└── requirements.txt
```

<Warning>
  **Never commit `.env` to Git.** Add it to `.gitignore` immediately:

  ```text theme={null}
  # .gitignore
  .env
  .venv/
  __pycache__/
  ```

  A `.env` file typically contains API keys, database passwords, and secret tokens. Exposing them in a public repository can lead to serious security breaches and unexpected billing charges.
</Warning>

## Sharing Projects Safely

Instead of sharing your real `.env`, create a template named **`.env.example`** with placeholder values:

```text theme={null}
OPENAI_API_KEY=your-api-key-here
DATABASE_URL=sqlite:///database.db
DEBUG=True
PORT=8000
```

Teammates copy it and fill in their own values:

```bash theme={null}
cp .env.example .env
```

## Best Practices

| Practice                 | Example                          |
| ------------------------ | -------------------------------- |
| Use UPPERCASE names      | `DATABASE_URL`, `API_KEY`        |
| One variable per line    | `PORT=8000`                      |
| No spaces around `=`     | `PORT=8000` ✅, `PORT = 8000` ❌   |
| Add comments for clarity | `# Database connection`          |
| Provide defaults in code | `os.environ.get("PORT", "8000")` |

## Common Environment Variables

```text theme={null}
# API Keys
OPENAI_API_KEY=...
GITHUB_TOKEN=...

# Database
DATABASE_URL=sqlite:///local.db

# Application Settings
DEBUG=True
PORT=8000

# Authentication
SECRET_KEY=super-secret-key

# Logging
LOG_LEVEL=INFO
```

Environment variables and `.env` files are a standard practice across all major Python frameworks — FastAPI, Flask, Django, and beyond. The pattern is the same everywhere: store configuration outside your code, load it at startup, and access it via `os.environ.get()`.
