'How to specify a BaseSettings Config's env_file based on a field from the same class?

I want to implement this logic

from pydantic import BaseSettings    

class Settings(BaseSettings):
    ENVIRONMENT: str = 'local'
    SECRET_KEY: str = 'somekey'
    
    class Config:
        env_file = ".env.development" if Settings.ENVIRONMENT == "development" else ".env.local" 

But I have an error:

NameError: name 'Settings' is not defined

I was trying self.ENVIRONMENT but it doesn't help.



Solution 1:[1]

Settings.ENVIRONMENT doesn't work because the Settings class isn't defined yet by the time it's referenced in the Config definition. And self.ENVIRONMENT doesn't work because self here would refer to the Config class, and not the Settings class, which as mentioned, isn't fully defined yet, let alone has loaded the value for ENVIRONMENT yet.

This design has a sort of circular dependency because the Settings object needs to be initialized first (from direct __init__ or environment variables or env files) to set an ENVIRONMENT value, ... but in order for Pydantic to initialize that class, it already needs to know which env_file to read to get the field values, ... but the env_file is determined by the ENVIRONMENT value, ... and so on.

The simple alternative would be to separate them into 2 BaseSettings classes instead:

class EnvConfig(BaseSettings):
    ENVIRONMENT: str = "local"

class Settings(BaseSettings):
    SECRET_KEY: str = "somekey"

Then create an instance of EnvConfig first, then reference that instance in defining Settings' Config.env_file:

class EnvConfig(BaseSettings):
    ENVIRONMENT: str = "local"

env_config = EnvConfig()

class Settings(BaseSettings):
    SECRET_KEY: str = "somekey"

    class Config:
        env_file = ".env.development" if env_config.ENVIRONMENT == "development" else ".env.local"
$ cat .env.local
SECRET_KEY=localkey
$ ENVIRONMENT=local python test.py
SECRET_KEY='localkey'

$ cat .env.development
SECRET_KEY=developmentkey
$ ENVIRONMENT=development python test.py
SECRET_KEY='developmentkey'

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Gino Mempin