Loading Configuration from External Sources
To populate your application configuration from external sources, use the methods provided by the Config class. This project follows a strict convention where only uppercase keys are loaded into the configuration dictionary.
Standard Configuration Pattern
The most common pattern in this codebase involves setting programmatic defaults and then overriding them with an external Python file if it exists.
import os
from flask import Flask
def create_app():
# instance_relative_config=True allows loading files relative to the instance folder
app = Flask(__name__, instance_relative_config=True)
# 1. Set programmatic defaults
app.config.from_mapping(
SECRET_KEY="dev",
DATABASE=os.path.join(app.instance_path, "flaskr.sqlite"),
)
# 2. Override from an external Python file (e.g., instance/config.py)
# silent=True prevents an error if the file is missing
app.config.from_pyfile("config.py", silent=True)
return app
Setting Defaults with Mappings
Use from_mapping to initialize configuration with a dictionary or keyword arguments. This is typically used in application factories like examples/tutorial/flaskr/__init__.py.
app.config.from_mapping(
DEBUG=True,
PORT=5000,
STORAGE_TYPE="local"
)
Loading from Python Modules or Classes
You can organize configuration into classes or modules and load them using from_object. This method only imports attributes that are in all uppercase.
# In a file named config_defaults.py
class DefaultConfig:
DEBUG = False
TESTING = False
DATABASE_URI = "sqlite:///:memory:"
# In your application setup
app.config.from_object("config_defaults.DefaultConfig")
Loading from Environment Variables
There are two primary ways to load configuration from environment variables: pointing to a file or loading prefixed variables directly.
Using a Configuration File Path
from_envvar loads a Python configuration file from a path stored in an environment variable.
# Set the variable in your shell:
# export YOURAPP_SETTINGS='/path/to/real_config.py'
app.config.from_envvar("YOURAPP_SETTINGS")
Loading Prefixed Variables Directly
from_prefixed_env loads all environment variables starting with a specific prefix (default is FLASK_). It automatically attempts to parse values as JSON (e.g., strings, numbers, booleans, or even nested dicts).
# Environment variables:
# FLASK_SECRET_KEY="production-key"
# FLASK_DATABASE__HOST="localhost"
# FLASK_DATABASE__PORT=5432
app.config.from_prefixed_env()
# Resulting config:
# app.config["SECRET_KEY"] == "production-key"
# app.config["DATABASE"] == {"HOST": "localhost", "PORT": 5432}
Loading from JSON or TOML Files
Use from_file to load configuration from non-Python formats. You must provide a loader function like json.load or tomllib.load.
import json
import tomllib
# Load from JSON
app.config.from_file("config.json", load=json.load)
# Load from TOML (requires text=False for binary read)
app.config.from_file("config.toml", load=tomllib.load, text=False)
Extracting Configuration Subsets
If you need to pass a group of settings to an external library, use get_namespace to extract keys sharing a common prefix.
app.config["DATABASE_HOST"] = "localhost"
app.config["DATABASE_USER"] = "admin"
# Extract all DATABASE_ settings
db_config = app.config.get_namespace("DATABASE_")
# db_config is now {"host": "localhost", "user": "admin"}
Troubleshooting and Gotchas
- Uppercase Only: Methods like
from_pyfile,from_object, andfrom_mappingignore any keys that are not fully uppercase. - Dictionaries vs. Objects:
from_objectworks on modules and classes by looking at attributes. It will not work on a standard dictionary because dictionary keys are not attributes. Usefrom_mappingfor dictionaries. - Environment Variable Types:
from_prefixed_envusesjson.loadsby default. If a value cannot be parsed as valid JSON, it will remain a string. - Windows Environment Keys: On Windows, environment variable keys are always uppercase. This can cause issues with
from_prefixed_envif you rely on specific casing for nested dictionary keys.