Why Typed Settings?

Comprehensive List of Features

  • Default settings are defined by your app and can be overridden by config files, environment variables and click options.

  • Settings are defined as attrs classes with types, (automatically generated) converters and validators.

    • Secrets are hidden when a settings instance is printed.

  • Options can be basic data types (bool, int, float, str), Enums, lists of basic types, or nested settings classes (full list).

    • An error is raised if options have an unsupported type

  • Settings can be loaded from multiple config files.

    • Settings files can be optional or mandatory.

    • Config files are allowed to contain settings for multiple apps (like pyproject.toml)

    • Paths to config files have to be explicitly named. There are no implicit default search paths.

    • Additional paths for config files can be specified via an environment variable. As in PATH, multiple paths are separated by a :. The last file in the list has the highest priority.

    • Extra options in config files (that do not map to an attribute in the settings class) are errors.

  • Environment variables with a defined prefix override settings from config files. This can optionally be disabled.

  • Click options for a settings class can be generated. They are passed to the cli function as a single object (instead of individually).

    • Click options support the same types as normal options.

    • Options can define a help-string for Click options.

  • Settings must be explicitly loaded, either via typed_settings.load_settings() or via typed_settings.click_options().

    • Both functions allow you to customize config file paths, prefixes et cetera.

  • Uses debug logging:

    • Config files that are being loaded or that cannot be found

    • Looked up env vars

What about Dynaconf?

Dynaconf seems quite similar to TS on a first glance, but follows a different philosophy.

Settings can be loaded from multiple config files and overridden by environment variables, but you don’t predefine the structure of your settings in advance. This makes defining defaults and validators for options a bit more tedious, but it is possible nonetheless.

Environment variables use the prefix DYNACONF_ by default which may lead to conflicts with other apps.

Dynaconf supports a lot more file formats than TS and can read secrets from HashiCorp Vault and Redis. TS may add support for these, though.

Settings can contain template vars (for Python format strings or Jinja) which are replaced with the values of loaded settings. Supported for this in TS is planned.

Dynaconf allows you to place the settings for all deployment environments (e.g., production and testing) into a single config file. I like to put these into different files since your configuration may consist of additional files (like SSH keys) that also differ between environments.

It seems like it is also not intended to share config files with other applications, e.g. in pyproject.toml.

Dynaconf can easily integrate with Flask and Django, but not with click.

What about environ-config?

Environ-config stems from the author of attrs and uses attrs classes to define the structure of your settings.

Settings can only be loaded from environment variables. Secrets can also be read from HashiCorp Vault, envconsul and ini files.

Additional config files are not supported which may lead to problems if your app needs more complex configuration.

Click is not supported.

It provides helpful debug logging and built-in dynamic docstring generation for the settings class.

What about Pydantic?

Pydantic is more comparable to attrs but also offers integrated settings loading (amongst many other features).

Settings classes are, as in TS and environ-config, predefined. Option values are automatically converted and can easily be validated.

Settings can only be loaded from environment variables (and .env files), though.