Flexible and secure .env loader for Python projects with support for environment switching, nested project structures, and external configuration directories.
dotenv-loader (Git, PyPI) provides a flexible yet straightforward way to load environment variables from .env
files, tailored specifically for Python applications, including Django, Flask, Celery, FastCGI, WSGI, CLI tools, and more. It supports hierarchical configuration, making it extremely convenient to manage multiple environments (development, testing, production) without manually switching .env
files or cluttering code with environment-specific logic.
Managing environment-specific settings is crucial in modern software development. The excellent python-dotenv package provides robust and versatile .env
file loading functionality, but it lacks flexible mechanisms for dynamically switching configurations across multiple deployment environments or nested project structures.
dotenv-loader is built upon python-dotenv
, enhancing it specifically to address the following practical challenges:
While dotenv-loader specializes in dynamic and hierarchical environment selection tailored for specific deployment scenarios, python-dotenv offers broader and more general-purpose capabilities. Users whose needs arenβt fully met by dotenv-loader
are strongly encouraged to leverage python-dotenv
βs comprehensive functionality directly.
DOTENV
environment variable.DOTCONFIG_ROOT
) with customizable subdirectories per project and environment stage (DOTSTAGE
)..env
file located directly in the project root.Dynamic project and stage selection: Quickly switch configurations by setting the DOTPROJECT
and DOTSTAGE
environment variables, allowing effortless toggling between multiple environments or projects.
.env
filenames to further separate and manage your configurations.Storing .env
files separately in a dedicated configuration directory (DOTCONFIG_ROOT
) outside your project source tree is a secure and recommended best practice. This approach significantly reduces the risk of accidentally leaking sensitive information (such as API keys, database credentials, etc.) during backups, version control operations, or file transfers. By keeping secrets separate from your codebase, dotenv-loader helps enforce a clear boundary between configuration and code, enhancing security and compliance.
pip install dotenv-loader
This package is tested on the following Python versions via GitHub Actions:
Python version | Status |
---|---|
3.9 | β Supported |
3.10 | β Supported |
3.11 | β Supported |
3.12 | β Supported |
3.13 | β Supported |
Automated tests are run on every push and pull request to ensure consistent support.
By default, dotenv-loader automatically identifies the .env
file from the current projectβs root directory:
import dotenv_loader
dotenv_loader.load_env()
import dotenv_loader
# Load environment with custom default settings
# Each parameter is optional and first four can be overridden by environment variables:
dotenv_loader.load_env(
project='mega-project', # - explicitly set project name
stage='production', # - explicitly set stage name
dotenv='./dir/.env.test' # - explicitly set .env file
config_root='~/custom-configs', # - custom config directory
steps_to_project_root=1, # - how many directories up to look for project root
default_env_filename='env', # - change the default '.env' name to you name
override=True # - whether to overwrite existing environment variables
# already defined in os.environ. Use False to preserve
# values already present (e.g. from OS or CI/CD), or
# True to always prefer .env contents.
)
You can control the behavior of dotenv-loader using the following environment variables:
FileNotFoundError
is raised.default_env_filename
and DOTSTAGE
(or fallback stage
).Examples:
DOTENV=/home/user/.env.custom python manage.py
# Uses this exact file; raises an error if not found
DOTENV=~/myconfigs/myproject python manage.py
DOTSTAGE=prod
# Loads ~/myconfigs/myproject/.env.prod
DOTENV=~/configs/project python manage.py # calling load_env(stage='local')
# Loads ~/configs/project/.env.local
DOTPROJECT=test python manage.py
# Loads: ~/.config/python-projects/test/.env
DOTSTAGE=staging python manage.py
# Loads: ~/.config/python-projects/myproject/.env.staging
DOTCONFIG_ROOT=~/myconfigs python manage.py
# Loads: ~/myconfigs/myproject/.env
DOTVERBOSE=1 python manage.py
# Output: Use DOTENV file from: /home/user/.config/python-projects/projectname/.env
~/.config/python-projects/
βββ myproject/
βββ .env # Default configuration (typically a symlink
β # to .env.prod)
β
βββ .env.prod # Production configuration. Use explicitly with:
β # DOTSTAGE=prod python manage.py
β
βββ .env.staging # Staging configuration. Use explicitly with:
β # DOTSTAGE=staging python manage.py
β
βββ .env.test # Testing configuration. Use explicitly with:
# DOTSTAGE=test python manage.py
myproject/
βββ manage.py # By default, loads ~/.config/python-projects/myproject/.env
.env # Used only if no .env.* files are found in
# ~/.config/python-projects/myproject
.env
Resolution Rules and Precedencedotenv-loader
uses a deterministic and secure resolution strategy when selecting the appropriate .env
file to load. The logic ensures maximum flexibility while maintaining clarity and safety.
Environment Variables Take Precedence
The following environment variables override their corresponding load_env()
arguments:
DOTENV
overrides dotenv
DOTPROJECT
overrides project
DOTSTAGE
overrides stage
DOTCONFIG_ROOT
overrides config_root
Relative Paths Are Context-Aware
Paths defined in environment variables (e.g., DOTENV
, DOTCONFIG_ROOT
) are resolved relative to the current working directory (PWD
, as seen with pwd
).
Paths passed directly to load_env()
(e.g., dotenv
, config_root
) are resolved relative to the calling scriptβs location, adjusted by steps_to_project_root
.
For example, if manage.py is at ~/projects/proj1/app/manage.py
and steps_to_project_root=1
, then project_root is considered to be ~/projects/proj1
.
Project and Stage Names Must Be Basenames
Both DOTPROJECT
/project
and DOTSTAGE
/stage
must not include slashes. They are treated strictly as simple names (i.e., Path(name).name
).
Highest Priority: Explicit .env Path or Directory
If either DOTENV
or dotenv
is defined, it takes priority over all other resolution logic.
FileNotFoundError
is raised and no fallback is attempted.[default_env_filename][.stage]
, where stage
comes from DOTSTAGE
or the stage
argument.Project Name Determination
The project name is determined as follows:
DOTPROJECT
or project
is defined, its basename is usedproject_root
directoryNote:
The project_root
is computed relative to the file that directly calls load_env()
, using the steps_to_project_root
parameter.
steps_to_project_root=0
(default), project_root
is the directory containing the calling filesteps_to_project_root=1
, itβs the parent of that directory, and so onFor example:
If load_env()
is called from ~/projects/proj1/app/manage.py
and steps_to_project_root=1
, then project_root = ~/projects/proj1
, and the fallback project name is proj1
.
.env Filename Construction
The .env
filename is constructed as:
"[default_env_filename][[.]STAGE]"
where:
default_env_filename
is .env
by defaultSTAGE
comes from DOTSTAGE
or stage
(if defined)Primary Search Location
If no explicit file path is provided via DOTENV
/dotenv
, the loader checks:
[DOTCONFIG_ROOT | config_root] / [DOTPROJECT | project] / [default_env_filename][.stage]
Fallback Location
If the file is not found in the config directory, a fallback search is performed in the computed project root:
[project_root] / [default_env_filename][.stage]
Error Handling
If no valid .env
file is found after all resolution attempts, a FileNotFoundError
is raised. The error message includes a list of all tried paths for easier debugging.
dotenv-loader is especially useful when:
We welcome contributions from the community! Please see CONTRIBUTING for details on how to get started.
This project was created in collaboration with ChatGPT (OpenAI), utilizing the GPT-4o, GPT-4.5, and GPT-3 models.
For detailed release notes, see CHANGELOG.
By clearly managing your environment variables and enabling dynamic configuration switching, dotenv-loader helps you streamline your deployment and development workflows, reduce errors, and maintain cleaner, more maintainable code.