Mastering Environment Variables in FastAPI with Pydantic
Managing environment variables securely is a vital part of crafting durable and flexible applications, especially when you’re diving into frameworks like FastAPI. These little key-value pairs let you configure your app without embedding sensitive data in your code, which is a game-changer. So let’s talk about how you can handle environment variables like a pro using FastAPI and Pydantic’s BaseSettings
.
What Even Are Environment Variables?
Think of environment variables as those sticky notes you put on your fridge. They’re key-value pairs sitting at the operating system level, controlling things like database URLs, API keys, and other secret stuff. This setup keeps your application safe and nimble, adapting smoothly across development, testing, and production environments without a hitch.
Starting with Environment Variables
First things first, you need the right tools. python-dotenv
is your go-to for managing environment variables from a .env
file. Trust me, it’s a lifesaver.
To install python-dotenv
, just run:
pip install python-dotenv
Once that’s done, create a .env
file in your project’s root directory. Toss in your environment variables like this:
DATABASE_URL=postgresql://user:password@localhost:5432/mydatabase
SECRET_KEY=mysecretkey
Now, before you hit run on your FastAPI app, make sure you load these environment variables with some easy-peasy code:
import os
from dotenv import load_dotenv
load_dotenv() # This loads environment variables from the .env file
Making Use of Environment Variables in FastAPI
After loading the environment variables, you can call on them within your app. Here’s a no-frills example:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
secret_key = os.environ.get("SECRET_KEY")
return {"Hello": "World", "Key": secret_key}
In this little snippet, SECRET_KEY
is fetched from the environment variables and popped into the response. Simple, right?
Cranking Up Complexity with Pydantic
For more intricate configurations, Pydantic’s BaseSettings
is your friend. It lets you define settings models to automatically pull from environment variables and validate data.
Install Pydantic if it’s not already hanging around:
pip install pydantic
Then, whip up a settings model:
from pydantic import BaseSettings
class Settings(BaseSettings):
app_name: str = "Awesome API"
admin_email: str
items_per_user: int = 50
class Config:
env_file = ".env"
Here, the Settings
class outlines several settings with some default values. The Config
class tells it to read from the .env
file.
Applying Settings in Your FastAPI App
Now, let’s bring these settings into your FastAPI app:
from fastapi import FastAPI, Depends
app = FastAPI()
settings = Settings()
@app.get("/info")
async def info():
return {
"app_name": settings.app_name,
"admin_email": settings.admin_email,
"items_per_user": settings.items_per_user
}
This ensures your app grabs settings from both the .env
file and any OS environment variables, prioritizing the OS.
Top Security Practices
Handling environment variables comes with the responsibility of keeping things secure:
- Don’t Commit Secrets: Never, ever commit your
.env
files or other sensitive files to version control. - Secure Methods: Use safe methods to set environment variables, especially in production. Hardcoding is your enemy.
- Test Thoroughly: Always double-check that your configurations load right and no sensitive data leaks.
Deployment Example
When it’s time to deploy, setting environment variables depends on your environment. For Unix-like systems, you might export variables in your terminal:
export ADMIN_EMAIL="[email protected]"
export APP_NAME="MyApp"
Run your FastAPI app with these settings:
fastapi run main.py
This ensures your app uses the right settings for the environment without tweaking the code.
Wrapping Up
Using environment variables in FastAPI with Pydantic’s BaseSettings
is a slick way to manage configurations and secure data. Follow these steps and nail those best practices to make sure your app stays flexible, secure, and super maintainable across various environments.
To see it all in action, here’s a full example to tie things together:
from fastapi import FastAPI
from pydantic import BaseSettings
from dotenv import load_dotenv
import os
load_dotenv() # Loads env vars from .env file
class Settings(BaseSettings):
app_name: str = "Awesome API"
admin_email: str
items_per_user: int = 50
class Config:
env_file = ".env"
settings = Settings()
app = FastAPI()
@app.get("/info")
async def info():
return {
"app_name": settings.app_name,
"admin_email": settings.admin_email,
"items_per_user": settings.items_per_user,
}
@app.get("/")
def read_root():
secret_key = os.environ.get("SECRET_KEY")
return {"Hello": "World", "Key": secret_key}
This example showcases how to load environment variables from a .env
file, craft settings with Pydantic, and integrate these settings into a FastAPI app. Follow these guidelines, and you’ll be building robust, secure, and maintainable applications in no time.