Python with Configuration File.
Reading configuration or properties file is a basic ingredient that is used in most of the scripting and full feature language. There are in-build library and other 3rd party library to read this type of type with ease. We can even use simple file reader but the ease of using such library makes the properties or configuration file awesome.
In python if you ever encounter to read such key/value type file, ConfigParser is the one that you should use. The Configparser module
contains most the needs that you would have to use a configuration type files and won’t need to implement your own parser.
First lets discuss what is what is configuration file type. If you are familiar you can skip this part.
Configuration File Type
Configuration file are those that have key/value type data. The separator would be either “:” or “=” with key in left side and value at right side. Comments are also allowed in such type with “#” or “;”. Leading white space are remove from the value. It also contain section part with “[this_is_section_header]” to differentiate and scope the keys. The file type can be of anything but mostly used are : cgf, ini, properties etc.
Example:
[Oracle]
# This is a comment
Username = ibobi
Password = passwd
Host = localhost
Sid = system
Port = 1521
[mysql]
Username = tom
Password = yahoo
Host = newHost
It also support interpolation
which means you can specify to refer other key(option) using “%option” but this can be parse using Configparser.SafeConfigParser().
[installation]
Home = /opt/app/oracle
Oracle.home = %home/product/db_1
Reading Configuration file
First import the require module.
from ConfigParser import SafeConfigParser, NoSectionError, NoOptionError
This is import SafeConfigParser to parse the configuration type file and the other two are the exception type that is used frequently.
NoSectionError :
Exception type raise when there is no section that is specified is found.
NoOptionError :
Exception type raise when there is no option that is specified is found.
The following will read the configuration file and return the SafeConfigParser instance that read the file.
def read_config_file(conf_file):
if not isfile(conf_file):
raise MyException("No File with name " + conf_file + " in " + getcwd())
conf = SafeConfigParser()
conf.optionxform = str
conf.read(conf_file)
return conf
Now you can define a function that extract the require information. This way you don’t have to read the file multiple time and use the instance.
#get oracle details
def get_install_dir(conf):
try:
username = conf.get('oracle', 'username')
print ‘Username is {0}’.format(username)
return username
except NoSectionError, msg:
print "Missing section [" + msg.section + "]"
except NoOptionError, msg :
print "Missing option '" + msg.option + "' of section [" + msg.section + "]"
You can even read all the keys/values in a section via
for key, value in conf.items('oracle'):
print ‘key = ’+ key + ‘ and value = ’+ value ‘\n’
Wrting to Configuration File
To write to Configuration file:
from ConfigParser import SafeConfigParser
config = SafeConfigParser()
def write_conf(section, option, value):
config.set(section, option, value)
my_dict = {'joe':'20', 'jone':'34', 'tom':'25', 'lucy':'26'}
config.add_section('Details')
for key,value in my_dict.iteritems():
write_conf('Details',key,value)
with open('hello.cfg','wb') as fp:
config.write(fp)
Reading configuration file without Section
Java property file with extension properties or any configuration that does not have section would be problem to read as the ConfigParser API need section to get the key/value.
lucy = 26
joe = 20
jone = 34
tom = 25
The solution is to create a fake section by initializing from a class and read the file. This way ConfigParser will see them with a face section.
from ConfigParser import SafeConfigParser
config = SafeConfigParser()
class FakeSecHead(object):
def __init__(self, fp):
self.fp = fp
self.sechead = '[asection]\n'
def readline(self):
if self.sechead:
try:
return self.sechead
finally:
self.sechead = None
else:
return self.fp.readline()
config.readfp(FakeSecHead(open('nosection.properties')))
config.items('asection')