Environment Variable Integration
Flask provides two primary ways to integrate environment variables into your application configuration: loading a configuration file via a path stored in an environment variable, or loading variables directly into the configuration object based on a prefix.
Loading from a Configuration File Path
When you need to keep sensitive information or environment-specific settings out of your source code, you can point Flask to a configuration file using an environment variable with from_envvar.
import flask
app = flask.Flask(__name__)
# Load configuration from a file path specified in the 'APP_SETTINGS' env var
app.config.from_envvar("APP_SETTINGS")
If the environment variable APP_SETTINGS is set to /var/www/app/config.py, Flask will execute that file and load its uppercase variables.
Handling Missing Variables
By default, from_envvar raises a RuntimeError if the environment variable is not set. You can suppress this by passing silent=True.
# Returns False instead of raising RuntimeError if 'OPTIONAL_SETTINGS' is missing
app.config.from_envvar("OPTIONAL_SETTINGS", silent=True)
Loading Prefixed Variables Directly
You can load environment variables directly into the Config object using from_prefixed_env. By default, it looks for variables starting with FLASK_.
import flask
import os
# Set environment variables (usually done in your shell)
# export FLASK_SECRET_KEY="local-dev-key"
# export FLASK_DEBUG="true"
app = flask.Flask(__name__)
app.config.from_prefixed_env()
print(app.config["SECRET_KEY"]) # "local-dev-key"
print(app.config["DEBUG"]) # True (automatically parsed)
Automatic Type Conversion
The from_prefixed_env method uses json.loads by default to attempt to parse values. This allows you to pass booleans, integers, lists, and dictionaries directly from the environment.
# export FLASK_PORT="5000" -> app.config["PORT"] == 5000
# export FLASK_ENABLED="true" -> app.config["ENABLED"] is True
# export FLASK_TAGS='["web", "v1"]' -> app.config["TAGS"] == ["web", "v1"]
If a value cannot be parsed as JSON, it remains a string.
Handling Nested Configuration
Flask supports populating nested dictionaries in your configuration by using a double underscore (__) as a separator in the environment variable name.
# export FLASK_DATABASE__HOST="localhost"
# export FLASK_DATABASE__PORT="5432"
app = flask.Flask(__name__)
app.config.from_prefixed_env()
# Resulting config structure:
# app.config["DATABASE"] == {"HOST": "localhost", "PORT": 5432}
If an intermediate key (like DATABASE in the example above) does not exist, Flask initializes it as an empty dictionary.
Customizing the Prefix and Parsing
You can change the prefix Flask looks for or provide a custom loading function for values.
import json
import flask
app = flask.Flask(__name__)
# Load variables starting with 'MYAPP_' instead of 'FLASK_'
app.config.from_prefixed_env(prefix="MYAPP")
# Use a custom loader (e.g., to disable JSON parsing and keep everything as strings)
app.config.from_prefixed_env(loads=lambda x: x)
Troubleshooting
Uppercase Key Requirement
Flask's Config class only tracks uppercase keys when loading from files or objects. While from_prefixed_env will load keys regardless of case (stripping the prefix), it is a standard convention in Flask to use uppercase for all configuration keys.
Windows Environment Variables
On Windows, environment variable keys are always uppercase. This can impact nested dictionary loading if your application logic expects specific casing for sub-keys. For example, FLASK_EXIST__ok will be read as FLASK_EXIST__OK on Windows, resulting in app.config["EXIST"]["OK"] instead of app.config["EXIST"]["ok"].
JSON Parsing Failures
If from_prefixed_env encounters a value that looks like JSON but is malformed, it catches the exception and treats the value as a raw string.
# export FLASK_DATA='{"key": "missing-quote}'
app.config.from_prefixed_env()
# app.config["DATA"] will be the literal string '{"key": "missing-quote}'