NefariousOctopus NefariousOctopus - 1 year ago 160
Python Question

Python setuptools: Distribute configuration files to OS specific directories

I am having kind of a chicken or the egg problem with Python setuptools.

What I am trying to achieve, is to distribute a configuration file with my pip package (which in itself is perfectly possible with

parameter in
) to OS specific common locations for user configuration files (e.g.
on Linux).

I figured out that OS "specificity" can be solved using
[1] PyPi package. And there is my problem - the
is not guaranteed to be installed when installing my own package since it is a dependency of my package and thus installed after it (promised chicken or the egg :) )

contains something like this:

from setuptools import setup
from appdirs import AppDirs
(AppDirs(name, author).user_config_dir, ['config/myconfig'])

Can this be solved without writing my own version of setuptools (allusion intended ;) )?


Answer Source

As I mentioned in my comment I would recommend distributing a generic copy of your file with your package and then copying it to the user's config dir at runtime if it does not exist.

This shouldn't be very hard and involves:

  1. Using setuptools's package_data (instead of data_files). This places the file where it is accessible at runtime using pkg_resources, in the "correct" location for the specific OS

  2. When the program runs, use appdirs to look for a user-specific, locally installed file.

  3. If it does not exist, use pkg_resources to find the file and copy it to the location provided by appdirs

While I haven't done this, this process should work nicely for multiple OSes and environments and as a bonus, during development too due to how pkg_resources works.


In, you should make sure to include your data file for your package using package_data:

    # ...
        "my_package": [ "my_package.conf.dist" 
    # ...

Example app code:

import os.path
import pkg_resources
import appdirs

def main():
    """Your app's main function"""
    config = get_config()
    # ... 
    # ...

def get_config():
    """Read configuration file and return its contents
    cfg_dir = appdirs.user_config_dir('MyApplication')
    cfg_file = os.path.join(cfg_dir, 'my_application.conf')
    if not os.path.isfile(cfg_file):
    with open(cfg_file) as f:
        data =
        # ... probably parse the file contents here ...
        return data

def create_user_config(cfg_file):
    """Create the user's config file

    Note: you can replace the copying of file contents using shutil.copyfile
    source = pkg_resources.resource_stream(__name__, 'my_package.conf.dist')
    with open(cfg_file, 'w') as dest:

I hope this clears up the usage of pkg_resources and package_data.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download