mikecharles
3/3/2016 - 6:59 PM

Load config data in a Python application from a default config file, and override some user-defined variables from a separate config file

Load config data in a Python application from a default config file, and override some user-defined variables from a separate config file

# Merge two dictionaries
def merge_dicts(default, user):
    default = copy.deepcopy(default)
    user = copy.deepcopy(user)
    if isinstance(user, dict) and isinstance(default, dict):
        for k, v in default.items():
            if k not in user:
                user[k] = v
            else:
                user[k] = merge_dicts(user[k], v)
    return user


# Load config data
def load_config():
    """
    Loads config values from the default config.yml file installed with the package,
    and overrides those values with values found in a config.yml file in ~/.config/<app-name>
    """
    # ----------------------------------------------------------------------------------------------
    # Load default config
    #
    try:
        default_config = yaml.load(resource_string('<app_name>', 'config.yml'))
    except Exception:
        print('Couldn\'t load default configuration data. Something went wrong with the '
              'installation.')
        sys.exit(1)
    # ----------------------------------------------------------------------------------------------
    # Load an optional config file with user-defined values that will override default values
    #
    # Try to read the config.yml file in ~/.config/<app-name>
    config_dir = os.path.expanduser('~/.config/<app-name>')
    try:
        with open('{}/config.yml'.format(config_dir)) as f:
            user_config = yaml.load(f)
    except FileNotFoundError:
        user_config = default_config
    except Exception:
        print('There was a problem reading ~/.config/<app-name>/config.yml')
        sys.exit(1)
    # If the user config file is empty, set the config data equal to the default data
    if not user_config:
        user_config = default_config
    # Override default values with the user-defined values
    try:
        config = merge_dicts(default_config, user_config)
    except UnboundLocalError:
        config = default_config
    # Return the config dict
    return config

Replace all instances of <app-name> with your app name (eg. 'my-python-app', dashes are allowed), and all instances of <app_name> with your app's main module (eg. 'my_python_app', dashes are NOT allowed), and