By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,646 Members | 1,175 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,646 IT Pros & Developers. It's quick & easy.

unified command line args, environment variables, .conf filesettings.

P: n/a
Just a fun exercise to unify some of the major input methods for a
script into a single dictionary.
Here is the output, given a gr.conf file in the same directory with
the contents stated below:

smitty@localhost ~/proj/mddl4/test $ ./inputs.py
{'source_db': '/home/sweet/home.db'}
smitty@localhost ~/proj/mddl4/test $ source_db="test_env" ./inputs.py
{'source_db': 'test_env'}
smitty@localhost ~/proj/mddl4/test $ ./inputs.py -f "test_cli"
{'source_db': 'test_cli'}
For the file
=========
#!/usr/bin/env python

#Goal: unification of environment variables, command line, and
# configuration file settings.
# The .conf file is the specification.
# Optional environment variables can override.
# Optional command-line inputs trump all.
# Example is a file spec for a source database for an application.
# .conf has a contents like:
#================================
# [CONF]
# source_db=/home/sweet/home.db

#TODO:
# 1. Decide (make an option?) to retain the simple dictionary or build
a
# class from the options.
# 2. Allow for multiple .conf locations, trying to be cool like
# xorg.conf

from ConfigParser import SafeConfigParser
from optparse import OptionParser
import os

CONF = "CONF" #section in .conf file
CONF_FILE = "gr.conf" #name of config file
PLACEBO = "placebo" #mindless default that we don't want
gconf = {} #all your config are belong to here
parser = OptionParser()
parser.add_option( "-f" , "--file"
, dest = "source_db"
, help = "source database"
, default = PLACEBO )
(cl_opts, args) = parser.parse_args()

config = SafeConfigParser()
config.read(CONF_FILE)
file_conf = dict(config.items(CONF))

for k in file_conf:

gconf[k]=file_conf[k]

if os.environ.has_key(k):
gconf[k] = os.environ[k]

if cl_opts.__dict__.has_key(k):
if cl_opts.__dict__[k]!=PLACEBO:
gconf[k] = cl_opts.__dict__[k]
print gconf
Jun 27 '08 #1
Share this Question
Share on Google+
3 Replies


P: n/a
smitty1e <sm******@gmail.comwrites:
Just a fun exercise to unify some of the major input methods for a
script into a single dictionary.
Here is the output, given a gr.conf file in the same directory with
the contents stated below:

smitty@localhost ~/proj/mddl4/test $ ./inputs.py
{'source_db': '/home/sweet/home.db'}
smitty@localhost ~/proj/mddl4/test $ source_db="test_env" ./inputs.py
{'source_db': 'test_env'}
smitty@localhost ~/proj/mddl4/test $ ./inputs.py -f "test_cli"
{'source_db': 'test_cli'}
A good start. However, you need to account for two conventions with
configuration of programs via environment variables:

* Environment variables that will be inherited by subprocesses are
conventionally distinguished from variables that will not be
inherited by using an UPPER_CASE name for variables (like process
config variables) that will be inherited, and a lower_case name for
variables (like local state variables) that will not be inherited.

* The process environment is a flat namespace, so config environment
variables need to be named to reduce the risk of namespace collision
with variables used by other programs. This is often done by
prefixing the name with the name of the program or system that will
consume it. e.g. The search path for Python imports is configured
via an attribute named 'path', but in the environment by a variable
named 'PYTHONPATH' (yes, I know that's not exactly equivalent, but
it's a good example).

Neither of these distinctions need to be made in a program-specific
configuration file, so these conventions don't apply there and would
be inappropriate. So you then need to deal with a configuration
setting being named one way in the environment, and another way in the
configuration file and elsewhere in the program.

This is probably best done by a mapping specifically for the
environment variable names:

config_env_names = {
'source_db': 'GR_SOURCE_DB',
}

and then referencing that dictionary when inspecting the environment:

for key in config.keys():
# ...
environ_name = config_env_names[key]
environ_value = os.environ.get(environ_name)
if environ_value is not None:
config[key] = environ_value
#...

--
\ "Pinky, are you pondering what I'm pondering?" "I think so, |
`\ Brain, but how will we get a pair of Abe Vigoda's pants?" -- |
_o__) _Pinky and The Brain_ |
Ben Finney
Jun 27 '08 #2

P: n/a
On May 2, 11:29 pm, Ben Finney <bignose+hates-s...@benfinney.id.au>
wrote:
smitty1e <smitt...@gmail.comwrites:
Just a fun exercise to unify some of the major input methods for a
script into a single dictionary.
Here is the output, given a gr.conf file in the same directory with
the contents stated below:
smitty@localhost ~/proj/mddl4/test $ ./inputs.py
{'source_db': '/home/sweet/home.db'}
smitty@localhost ~/proj/mddl4/test $ source_db="test_env" ./inputs.py
{'source_db': 'test_env'}
smitty@localhost ~/proj/mddl4/test $ ./inputs.py -f "test_cli"
{'source_db': 'test_cli'}

A good start. However, you need to account for two conventions with
configuration of programs via environment variables:
[snip]
This is probably best done by a mapping specifically for the
environment variable names:

config_env_names = {
'source_db': 'GR_SOURCE_DB',
}

and then referencing that dictionary when inspecting the environment:

for key in config.keys():
# ...
environ_name = config_env_names[key]
environ_value = os.environ.get(environ_name)
if environ_value is not None:
config[key] = environ_value
#...
Hmmm...
I kinda think your excellent points are more in the realm of policy
than mechanism.
What I was going for was to assert that there a designated section (of
many possible ones)
in a .conf file that represents the set of possible program inputs,
and then
offering an example of letting environment and command line arguments
override that
..conf section.
Your points for reducing collision are well taken. Possibly having a
removable prefix
(which could be a "magic" .conf entry) would allow for a de-conflictor
prefix like
MY_PROGRAM_REALLY_ROCKSsource_db without having to propagate such an
eyesore throughout
the program code.
In any case, it stands as a fun little worked example.
R,
C
Jun 27 '08 #3

P: n/a
On May 3, 12:16 pm, smitty1e <smitt...@gmail.comwrote:
Just a fun exercise to unify some of the major input methods for a
script into a single dictionary.
Here is the output, given a gr.conf file in the same directory with
the contents stated below:

How about extending this to include other sources of control inputs.
I think a reasonable heirarchy is:

Interactive Input
Command Line Argument
Command Line Input File
Environment Variables
Local Defaults File
System Wide Defaults File
Installation Defaults File
'Factory' Defaults File
In-Code Initialization Defaults
Jun 27 '08 #4

This discussion thread is closed

Replies have been disabled for this discussion.