Python CLI and configuration file parser
17/Nov 2011
One of the first things I needed writing the code for my thesis was the ability to read options and parameters both from a configuration file and from the command line. After some attempts I have found (at http://www.decalage.info) a file parser to read a configuration file and the Python library argparse for the command line parsing. In addition I have modified the file parser and I’ve added a “variable container” object, inspired by some snippets found somewhere on the web.
I chose to first parse the configuration file and after the command line options: if it’s necessary the command line options will overwrite the file options.
Let’s consider the code, fully commented.
import argparse
def parse_config(filename):
"""Read the config file and store the variables into a dictionary.
Thanks to http://www.decalage.info
"""
mlogger.info("Reading config file.")
COMMENT_CHAR = '#'
OPTION_CHAR = '='
options = {}
f = open(filename)
for line in f:
# First, remove comments:
if COMMENT_CHAR in line:
# split on comment char, keep only the part before
line, comment = line.split(COMMENT_CHAR, 1)
# Second, find lines with an option=value:
if OPTION_CHAR in line:
# split on option char:
option, value = line.split(OPTION_CHAR, 1)
# strip spaces:
option = option.strip()
value = value.strip()
# store in dictionary:
options[option] = value
f.close()
return options
And this is the container for the variables, also clearly commented.
class Bunch(object):
"""Create a dictionary object containing all the initial variables.
"""
def __init__(self, d=None):
if d is not None: self.__dict__.update(d)
def var(filename):
"""Read the initial variables and return a dictionary object.
Parameters
==========
filename = string, the name of the config file
Returns
=======
Bunch(locals()) = dictionary object containing the local variables
"""
# Read the config file and create a dictionary.
options = parse_config(filename)
# Common variables.
mlogger.info("Defining common parameters.")
parameter_1 = options['parameter_1']
parameter_2 = options['parameter_2']
parameter_3 = None
option_1 = False
return Bunch(locals())
Now the commented code for the command line parsing.
# Read the configuration file.
v = mod.var('../config.txt')
# Check if there are CLI arguments, if yes start parsing.
if argv is None:
# Check for CLI variables.
argv = sys.argv
# Create the parser object.
parser = argparse.ArgumentParser()
# Create the parser entry.
parser.add_argument('-p1', '-parameter_1', '--parameter_1', action='store', dest='parameter_1', default=v.parameter_1,
help='Parameter 1 description')
parser.add_argument('-p2', '-parameter_2', '--oparameter_2', action='store', dest='parameter_2', default=v.parameter_2,
help='Parameter 2 description')
parser.add_argument('-o', '--option', action='store_true', dest='option', default=None,
help='Oprion description')
# Add the parsed variables to a container object
cli = parser.parse_args()
# Overwrite the config file parameters
v.parameter_1 = cli.parameter_1
v.parameter_2 = cli.parameter_2
v.option = cli.option
elif isinstance(argv, dict):
# Reading variables passed to Main as a function (Guido docet
# http://www.artima.com/weblogs/viewpost.jsp?thread=4829).
for i in argv.keys():
if i in ("-p1", "--parameter_1"):
v.parameter_1 = argv[i]
elif i in ("-p2", "--parameter_2"):
v.parameter_2 = argv[i]
elif i in ("-o", "--option"):
v.option = True
else:
print "Wrong parameter passed to main function, exit!!!"
sys.exit(1)
The configuration file look like this:
# Short description of parameter 1
parameter_1 = value
# Short description of parameter 2
parameter_2 = None