User (or admin) editable configuration file

This seems like a reasonable place to ask this. It isn’t about packaging exactly, but certainly related.

I’d like to have a human-editable configuration file that affects the behavior of a python package. The exact use case isn’t important for this discussion, but an example might be the SMTP servers and ports for a set of email domains.

The package would likely have some defaults, but it would support a human-editable file for local extensions or modifications. (/etc would be a logical location on a linux system.)

And it would be preferable if the configuration could be localized in a virtual environment.

I suppose it could go looking for configuration files, for example:

  • /etc/packagename.conf
  • $HOME/config/packagename.conf
  • $VIRTUAL_ENV/config/packagename.conf
  • built-in defaults

and merge them appropriately. Or maybe take the first one found (not in the above order) and use that. But that seems convoluted.

Suggestions, anyone?

What you suggest sounds reasonable. If you want it to be cross-platform, you can use platformdirs for os-specific locations.

If you think that’s convoluted, wait till someone asks for the ability to override via environment variables or command line options!

It’s quite possible there’s a library for this on PyPI. I haven’t checked, though.

Thanks for the pointer to platformdirs. I knew I was going to have to deal with that but hadn’t gotten to the point of thinking about it. I’m reasonably comfortable with Python for just my own usage. This is my first attempt at considering something that might be generally useful (for a fairly specific audience). And looking at platformdirs gives me some ideas of how to do things.

And I already planned to support specifying an alternate location for the configuration file as an option. That’s the easy part.

There used to be something called configglue, but looking back at that now, it looks like it’s been largely abandoned, and was never ported to argparse. Probably there are many others - pretty much everyone faces this particular integration challenge at some point.

@urbanian : In general, there’s some pretty good arguments for separating changeable config out from code, how far you take that is up to your planned uses.

@ mwichmann: That’s pretty much my goal here, to keep actual values out of the code. The configuration would provide values to be used for different site (or user) defined use cases, even though there may be a few well-known cases that could be defaults in the package. (But the defaults could be overridden by the installation or user if necessary.

Taking the example in my original post, the SMTP server and port for email addresses are well known and would be built in, but I wouldn’t try to pre-define all of the other domains supported by the Yahoo infrastructure.

And at this point I’m only providing a callable library, not a command. Any command-line setting of the configuration would just provide an alternate configuration file, probably replacing all of the built-in files. (Or maybe to be merged with the others? I haven’t thought that through. Maybe that’s best.)

In some of my projects I am using confuse:

It is able to combine multiple configuration files together and has built-in support for configuration directories like $XDG_CONFIG_HOME etc. The library is able to read a configuration template distributed with your Python package and automatically use a configuration directory based on your application name.

The way of creating the configuration scheme (parameters and their data types) seems reasonable.

What I am not a fan of in this library:

  • Use of the overcomplicated YAML format.
  • There is not a single API call to write the configuration to configuration files but for my use-case the function to do that is very simple (few lines).
  • The library is able to keep comments when writing to a configuration file but they must start at the beginning of lines (no leading spaces).
  • There is no built-in support for type annotations for the configuration parameters.
1 Like