How to pass env file to FastAPI app via command line

Viewed 59

I have the following file that reads in an .env file:

from pydantic import BaseSettings, HttpUrl


class Settings(BaseSettings):
    url: HttpUrl

    class Config:
        env_file = "config.env"

settings = Settings()

What do I need to do to be able to pass config.env on start?

So python -m uvicorn main:app --reload --env config.env

Is there any help FastApi or Uvicorn provide for this?

3 Answers

You can pass all the envs from config.env using python-dotenv . To pass a custom path (from): https://stackoverflow.com/a/50356056/14882170

import os
from dotenv import load_dotenv

# Get the path to the directory this file is in
BASEDIR = os.path.abspath(os.path.dirname(__file__))

# Connect the path with your '.env' file name
load_dotenv(os.path.join(BASEDIR, 'config.env'))

test_var = os.getenv("TEST_VAR")

print(test_var)

Because this is your custom code block, so uvicorn or starlette don't support this. I think you should custom your command line by Typer. Then you can pass env file by command line.

From the docs posted here, you need call the variables from the .env class in the Settings class.

config.py

from pydantic import BaseSettings

class Settings(BaseSettings):
foo: str

class Config:
    env_file = "config.env"

where config.env has the following:

foo="bar"

Then you pass the contents to the get_settings function wrapped by a lru_cache decorator and return those values.

@lru_cache()
def get_settings():
  return config.Settings()

After that you can inject those parameters into the "/info" path of the fastapi app:

@app.get("/")
def read_root():
  return {"Hello": "World"}


@app.get("/info")
async def info(settings: config.Settings = Depends(get_settings)):
  return {"foo": settings.foo}

The full main.py should be like this:

from functools import lru_cache
  from fastapi import Depends, FastAPI
  import config

  app = FastAPI()


  @lru_cache()
  def get_settings():
    return config.Settings()


  @app.get("/")
  def read_root():
    return {"Hello": "World"}

  @app.get("/info")
  async def info(settings: config.Settings = Depends(get_settings)):
    return {"foo": settings.foo}

Then just start your app without calling the env file in the command:

python -m uvicorn main:app --reload 

The curl output should be something like this:

curl http://127.0.0.1:8000/info
{"foo":"bar"}  
Related