Skip to content

franktz/dynamic-config-nacos

Repository files navigation

dynamic-config-nacos

English | 简体中文

dynamic-config-nacos is a small reusable Python package for dynamic configuration loading.

Its goal is to give application projects one consistent way to read configuration, whether the source is a local YAML file or a Nacos server.

Author: FrankTang (franktz2003@gmail.com)

License: MIT

What This Library Does

  • Uses local YAML as a fallback configuration source
  • Fetches remote configuration from Nacos
  • Supports automatic backend selection across http, sdk_v2, and sdk_v3
  • Refreshes in-memory configuration on updates on a best-effort basis
  • Provides a lightweight Conf object for dot-path and index-based access

Install

pip install dynamic-config-nacos

The Python import name remains dynamic_config:

from dynamic_config import DynamicConfigProvider

For local workspace development with uv, downstream projects can also use a path dependency to this package.

Quick Start

from dynamic_config import DynamicConfigProvider

provider = DynamicConfigProvider(local_yaml_path="configs/local.yaml")
provider.load_from_env()

app_name = provider.get("app.name")

Usage

Local YAML Only

from dynamic_config import DynamicConfigProvider

provider = DynamicConfigProvider(local_yaml_path="configs/local.yaml")
provider.load_initial(None)

debug = provider.get("app.debug", False)

Enable Nacos with Environment Variables

$env:NACOS_SERVER_ADDR = "127.0.0.1:8848"
$env:NACOS_DATA_ID = "app.yaml"
$env:NACOS_GROUP = "DEFAULT_GROUP"
from dynamic_config import DynamicConfigProvider

provider = DynamicConfigProvider(local_yaml_path="configs/local.yaml")
provider.load_from_env()

app_name = provider.get("app.name")

Override the Local YAML Path

DynamicConfigProvider currently requires a local_yaml_path value during construction, but load_from_env() will override it if LOCAL_CONFIG_PATH is set.

$env:LOCAL_CONFIG_PATH = "configs/dev.local.yaml"

After load_from_env(), the library will use the path from LOCAL_CONFIG_PATH.

Read Values Through Conf

conf = provider.conf

value1 = conf["a.b[0].c"]
value2 = conf.a.b[0].c
value3 = conf.get("a.x", "fallback")

Logging

This package uses the standard library logging module and does not currently accept a custom logger object from callers.

Internally it uses module-level loggers like this:

logger = logging.getLogger(__name__)

That means the host application controls log output, handlers, formatting, and log levels:

import logging

logging.basicConfig(level=logging.INFO)

Typical log events include:

  • warning when the local YAML file is missing
  • warning when Nacos returns a non-mapping YAML root
  • warning for invalid backend or polling interval values
  • info when a watcher has started, including the backend and polling interval for HTTP mode
  • info when a Nacos update has been applied
  • info when a backend is auto-selected
  • exception when Nacos fetch, watcher startup, login, or version detection fails

Separate nacos-python-sdk Logs

If you use sdk_v2 or sdk_v3, you can route SDK logs to a dedicated path without changing your application's root logger setup:

from dynamic_config import DynamicConfigProvider, NacosBackendType, NacosSettings

provider = DynamicConfigProvider(local_yaml_path="configs/local.yaml")
provider.load_initial(
    NacosSettings(
        server_addr="127.0.0.1:8848",
        namespace=None,
        data_id="app.yaml",
        group="DEFAULT_GROUP",
        backend=NacosBackendType.SDK_V3,
        sdk_log_level="ERROR",
        sdk_log_path="logs/nacos.log",
    )
)

You can also configure the same behavior through environment variables:

$env:NACOS_SDK_LOG_LEVEL = "ERROR"
$env:NACOS_SDK_LOG_PATH = "logs/nacos.log"

sdk_log_path accepts either a directory or an explicit log file path. When you pass a file path such as logs/nacos.log, the SDK logs are written to that exact file.

SDK Compatibility Note

If you install the current nacos-sdk-python 3.x line, the supported SDK path in this package is sdk_v3.

In auto mode, the package now prefers sdk_v3 when that is the only installed SDK-backed import path available. sdk_v2 is retained for older environments that still provide the legacy nacos package import.

Does the Local YAML File Need to Exist?

  • local_yaml_path is currently a required constructor argument
  • The file itself does not need to exist
  • If the file is missing, the library logs a warning and falls back to an empty config {}
  • If Nacos successfully returns a config, the local YAML file is not used for that load

In practice, the path behaves more like a local fallback location than a strict required input file.

Internal Design Overview

The library's loading flow looks like this:

  1. Create DynamicConfigProvider with a local YAML path.
  2. Call load_from_env() to read Nacos-related environment variables.
  3. If NACOS_SERVER_ADDR is present, build a NacosSettings object.
  4. Create a Nacos backend using explicit configuration or auto-detection.
  5. Try to fetch YAML content from Nacos first.
  6. If Nacos fails, returns empty content, or returns a non-mapping YAML root, fall back to the local YAML file.
  7. Store the final raw dictionary and wrap it in a Conf object.
  8. If the backend supports watching, start a watcher and refresh the in-memory config on updates.

Auto Backend Selection

When backend=AUTO, the package first tries to detect the Nacos server major version over HTTP and then picks a preferred order:

  • Nacos 2.x: sdk_v2 -> sdk_v3 -> http
  • Nacos 3.x: sdk_v3 -> sdk_v2 -> http
  • Detection failed: sdk_v3 -> sdk_v2 -> http

After building that preferred order, the package filters out SDK paths that are not actually importable in the current Python environment. For example, if only v2.nacos is installed, auto skips sdk_v2 and goes straight to sdk_v3.

HTTP Mode

  • Fetches config through the Nacos HTTP API
  • Optionally logs in first to obtain an accessToken
  • Starts a background polling thread
  • Logs watcher startup with the active backend and polling interval
  • Uses content MD5 to detect changes
  • Logs when an updated config has been applied

SDK Mode

  • Tries multiple SDK import paths
  • Tries both get_config and getConfig
  • Tries add_config_watchers, add_config_watcher, and add_listener

Public API

  • DynamicConfigProvider
  • Conf
  • NullConf
  • NULL
  • NacosSettings
  • NacosBackendType

Additional Docs

Project Links

Author

About

Reusable dynamic config provider with YAML fallback and Nacos backends

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors