views:

293

answers:

4

I am developing a project that requires a single configuration file whose data is used by multiple modules.
My question is: what is the common approach to that? should i read the configuration file from each of my modules (files) or is there any other way to do it?

I was thinking to have a module named config.py that reads the configuration files and whenever I need a config I do import config and then do something like config.data['teamsdir'] get the 'teamsdir' property (for example).

response: opted for the conf.py approach then since it it is modular, flexible and simple

I can just put the configuration data directly in the file, latter if i want to read from a json file a xml file or multiple sources i just change the conf.py and make sure the data is accessed the same way.

accepted answer: chose "Alex Martelli" response because it was the most complete. voted up other answers because they where good and useful too.

+3  A: 

The approach you describe is ok. If you want to add support for user config files, you can use execfile(os.path.expanduser("~/.yourprogram/config.py")).

Otto Allmendinger
Your answer implies that the config files are python source code. I like and use this approach, but one has to be aware that users can put arbitrary python code into these file which gets executes inside the application. This may create security and other issures like impossible-to-debug, site specifc problems.
Ber
@Ber: The users have *all* of the Python source to edit. Why mess with doctoring a configuration file? They can change *anything* in a Python application. The "arbitrary python code into these file" doesn't make sense when it's easier to simply modify the application itself.
S.Lott
@Ber if someone has access your config file, you are in trouble already. Also the user doesn't really have to know that it is a python file, a simple config file can still be `username = "Foo"; password="Bar"`
Otto Allmendinger
@S.Lott You can deliver a Python app as compiled code (.pyc/.pyo), so source need not be visible. You can use access control to deny changes to central system control files. A user config file such as ~/.config.py creates the said security issues, whereas a different kind of config file does not.
Ber
"Never attribute to malice that which can be adequately explained by stupidity." Even if the user doesn't want to do any harm, he might do this unintentionally. Executing arbitrary python code supplied by the users, makes this easier
bgbg
+2  A: 

One nice approach is to parse the config file(s) into a Python object when the application starts and pass this object around to all classes and modules requiring access to the configuration.

This may save a lot of time parsing the config.

Ber
my intention was to avoid this approach since it is not very practical to pass the object around...
João Portela
@João Portela this is a matter of your application's architecture. I think its ofter better to pass around some explicit context than accessing global stuff from all over the place.
Ber
i understand that, but for me it didn't make much sense in the context of my project. (+1 for showing that are other options)
João Portela
+3  A: 

I like the approach of a single config.py module whose body (when first imported) parses one or more configuration-data files and sets its own "global variables" appropriately -- though I'd favor config.teamdata over the round-about config.data['teamdata'] approach.

This assumes configuration settings are read-only once loaded (except maybe in unit-testing scenarios, where the test-code will be doing its own artificial setting of config variables to properly exercise the code-under-test) -- it basically exploits the nature of a module as the simplest Pythonic form of "singleton" (when you don't need subclassing or other features supported only by classes and not by modules, of course).

"One or more" configuration files (e.g. first one somewhere in /etc for general default settings, then one under /usr/local for site-specific overrides thereof, then again possibly one in the user's home directory for user specific settings) is a common and useful pattern.

Alex Martelli
+1  A: 

If you want to share your config across different machines, you could perhaps put it on a web server and do import like this:

import urllib2
confstr = urllib2.urlopen("http://yourhost/config.py").read()
exec(confstr)

And if you want to share it across different languages, perhaps you can use JSON to encode and parse the configuration:

import urllib2
import simplejson
confstr = urllib2.urlopen("http://yourhost/config.py").read()
config = simplejson.loads(confstr)
sharjeel