[Tutor] where to put configuration files: Solution!

Paul Tremblay phthenry at earthlink.net
Thu Nov 6 03:26:46 EST 2003


A while back, I started a thread on where to put configuration files.
There seemed to be no good solution. 

Jeff Shannon summed up the problem when he wrote "The problem is that
there is no good cross-platform way to store configuration files... It
does seem to me that a transparent cross-platform config manager, a la
wxConfig, would be a very useful addition to the Python standard
library."

Since wxConfig does not exist, I have come up with a satisfactory
solution. Others might find this solution useful, so I posted it below.

PROBLEM
=======

Your script must read certain data files yet cannot know where to put
them so that all users on any system will have access to them. A seeming
solution is to put the files in the same file as the modules. But you
cannot use this method if you use disutils to install your package.
disutils will not put data files in the same locaton as the packages or
the script. 


SOLUTION
========

Write a configuration utility that determines the location of the data
files and writes a module to give the script access to this location. 

The configuration script might look like this:

#!/usr/bin/env python

"""

Get the desired location of a the data files, and write a module to give
access to this location

Write a one line file of the location of the target files.


"""
import os, sys

def do_location():

	"""

	The target is the first system argument. Use the target to write
	a simple script to access the location.


	"""
	target = sys.argv[1]
    	the_dir = os.path.join(target, 'data_dir')
	
	# write the module
    	write_obj = open('module_name/configuration_dir.py', 'w')
	write_obj = open(the_dir, 'w')
    	write_obj.write( 'def get_dir():\n'
	'     return "%s"' % the_dir)
	write_obj.close()

	# write the data_location file 
	write_obj = open('data_location', 'w')
	write_obj.write(target)
	write_obj.close()


if __name__ == '__main__':
	do_location()

***

Once the user runs python configure.py, two new files will be created.
The first, a modlue, looks like this:

def get_dir()
    return "/path/data_dir"

This simple two-line module is located within the package of your other
modules, so it will get put in the right place.

The second file created by configure.py is a one line file called
"data_location". It  has one line--the location of the data files. If
the user choose "/etc," it would look like this:

/etc

Your setup.py file will look like this:

import sys, os
from distutils.core import setup

from distutils.core import setup

data__file_exists = os.path.isfile('data_location')
if not data_file_exists:
    sys.stderr.write('Please run python configure.py first\n')
    sys.exit(1)
read_obj = open('data_location', 'r')
lines = read_obj.readlines()
read_obj.close()
data_location = lines[0]
data_location = os.path.join(data_location, 'data_dir')


setup(name="module_name",
    version= '.4' ,
    description="Perform a certain function",
    author="First Last",
    author_email="myemail at provider.net",
    license = 'GNU GPL',
    url = "http://module_name.sourceforge.net/",
    packages=['package_name'],
    scripts=['scripts/script_name'],
    data_files = [
        (data_location, ['data/configure.txt']),
   )

***

The user types:

python setup build
python setup install

All the scripts, modules and data files get put in the right place.

Now your main script can have access to the data files, no matter where
they are. For example, you main script might look like this:


#!/usr/bin/env python

import module_name.configuration_dir
data_dir = module_name.configuration_dir.get_dir()

Any files you need will be located within data_dir.
For example, if you needed to read a configuration file, you might
write:

config_file = os.path.join(data_dir, 'configuration.txt')
read_obj = open(config_file, 'r')

This solution works as long as your script has multiple modules located
within a package called "module_name." If your script consisted of only
one module, or just the executable itself, you would have to tinker with
this solution--though I wouldn't think too much. 

For example, if your script consited of just one file, you could still
write the get_directory module and store it in the same directory as
the script. Make sure you tell setup.py to see this new two-line module
as a module that needs to be installed. And of course, since the
two-line module would reside in the same directory as any other module,
give it a unique name. That is, instead of calling it
"configuration_dir.py," call it "my_module_name_configuration.py."

In addition, you probably want to make your configuration.py file
perform a lot more functions. For example, it should check that the
target is a valid directory, and that the user can install to this
directory.

Paul



-- 

************************
*Paul Tremblay         *
*phthenry at earthlink.net*
************************



More information about the Tutor mailing list