Manage dev/prod config in pure Python

2 minute read

I’d like to separate dev/test/prod environments :) so let’s see the real example.

Audience

Developers, DevOps Engineers, and SysAdmins.

Challenges

  • Put configs in a simple format (JSON, YAML, …)
  • Hide unnecessary config information from other envs

Structure

I will put my configs in “etc” folder in the root of the project:

├── config-dev.yml
├── config-prod.yml
└── config.yml

config.yml

Then specify the current env inside “config.yml”, this is my config.yml file content:

# config.yml
profiles:
    active: dev

config-dev.yml

Now I want to read the redis configuration from “config-dev.yml”:

# config-dev.yml
redis:
    host: localhost
    port: 6379
    history-sub: history-subscriber

config.py

It’s time to read these values inside python, this is my “config.py” file:

# config.py
from loguru import logger

get = None
CONFIG_PATH_FROMAT = 'etc/config%s.yml'

def load():
    logger.add("logs/app.log", rotation="10 MB", compression="zip", level="INFO")
    active_profile = read(load_config(''))['profiles']['active']
    logger.info("Config active profile \"%s\" is loaded..." % active_profile)
    global get
    get = read(load_config(active_profile))


def read(path):
    with open(r'' + path) as file:
        return yaml.load(file, Loader=yaml.FullLoader)


def load_config(active_profile):
    if active_profile == '':
        return CONFIG_PATH_FROMAT % ''
    else:
        return CONFIG_PATH_FROMAT % ('-' + active_profile)

main.py

Now we need to load our config loader once then use it anywhere we like, add these lines to you main module:

# main.py
from config import config

def main():
    config.load()
    redis_port = config.get['redis']['port']
    print('redis_port', redis_port)


if __name__ == "__main__":
    main()

The final word

The only issue is that you can not change the structure of “config.yml”, and the other files structures just depend on you.