Skip to main content

Managing Configuration Namespaces

When you integrate third-party libraries like Celery or a custom storage engine into a Flask application, you often need to pass a specific subset of configuration settings to their constructors. Instead of manually picking keys from app.config, Flask provides tools to isolate and manage these settings using namespaces.

Extracting Configuration Subsets​

If your configuration contains many keys with a common prefix, you can use get_namespace to extract them into a separate dictionary. This is particularly useful for passing keyword arguments to external classes or functions.

app.config["IMAGE_STORE_TYPE"] = "fs"
app.config["IMAGE_STORE_PATH"] = "/var/app/images"
app.config["IMAGE_STORE_BASE_URL"] = "http://img.website.com"

# Extract settings starting with 'IMAGE_STORE_'
image_store_config = app.config.get_namespace("IMAGE_STORE_")

The resulting image_store_config dictionary will look like this:

{
"type": "fs",
"path": "/var/app/images",
"base_url": "http://img.website.com"
}

How get_namespace Works Internally​

The Config.get_namespace method in flask/config.py iterates through all configuration items and filters for keys that start with the provided string. By default, it performs two transformations:

  1. Trimming: It removes the namespace prefix from the keys (controlled by trim_namespace=True).
  2. Lowercasing: It converts the remaining key to lowercase (controlled by lowercase=True).

This behavior is designed to match the common Python pattern where configuration constants are UPPERCASE but function arguments are lowercase.

Loading Prefixed Environment Variables​

Modern applications often use environment variables for configuration. Flask supports loading these into specific namespaces using from_prefixed_env. This method allows you to group related settings and even create nested dictionary structures.

# In your shell:
# export FLASK_DATABASE__HOST=localhost
# export FLASK_DATABASE__PORT=5432

app.config.from_prefixed_env()

After calling this, app.config["DATABASE"] will contain {"HOST": "localhost", "PORT": "5432"}.

Handling Nested Structures​

The from_prefixed_env method uses a double underscore (__) as a separator to indicate nesting. When it encounters a key like FLASK_DATABASE__HOST, it:

  1. Removes the FLASK_ prefix.
  2. Splits the remaining string DATABASE__HOST by __.
  3. Ensures app.config["DATABASE"] is a dictionary.
  4. Sets the HOST key within that dictionary.

Type Conversion​

By default, from_prefixed_env attempts to parse environment variable values as JSON using json.loads. This allows you to pass booleans, integers, or even full JSON objects/lists through environment variables. If parsing fails, the value remains a string.

# export FLASK_DEBUG=true
# export FLASK_RETRY_LIMIT=5

app.config.from_prefixed_env()
# app.config["DEBUG"] is True (bool)
# app.config["RETRY_LIMIT"] is 5 (int)

Practical Example: Celery Integration​

A common pattern in Flask is to define default settings in a dictionary and allow environment variables to override specific nested values. This is frequently seen in Celery integrations within Flask.

from flask import Flask

def create_app() -> Flask:
app = Flask(__name__)

# Define default nested configuration
app.config.from_mapping(
CELERY=dict(
broker_url="redis://localhost",
result_backend="redis://localhost",
task_ignore_result=True,
),
)

# Allow overrides via environment variables
# e.g., FLASK_CELERY__BROKER_URL=redis://production-redis
app.config.from_prefixed_env()

return app

In this scenario, from_mapping ensures that the CELERY key exists as a dictionary. When from_prefixed_env runs, it traverses into that existing dictionary to update specific keys if the corresponding environment variables are set.

Important Constraints​

When managing namespaces, keep the following Flask behaviors in mind:

  • Uppercase Filtering: Methods like from_object, from_pyfile, and from_mapping only process keys that are entirely uppercase. This prevents internal attributes or temporary variables in config files from accidentally entering your application configuration.
  • Case Sensitivity: While get_namespace defaults to lowercasing keys for usage in Python code, the keys stored inside app.config itself are case-sensitive.
  • Windows Environment Variables: On Windows, environment variable keys are always uppercase. This means from_prefixed_env will always result in uppercase keys (or nested keys) when running on Windows, regardless of how they were defined in the shell.