Serialize INI configuration to python dictionary
August 30th, 2009 mysurface Posted in Developer, python | Hits: 72156 |
A lots of configuration file is in the format of INI, if we manage to serialize INI configuration to python dictionary, we can write python scripts to analyse and generate back to INI files.
Below is the sample of INI configuration: config.ini
#
# GENERAL section contains generic configuration
#
[GENERAL]
IP=192.168.1.4
Port=2143
#
# LOG section contains logging settings
#
[LOG]
LogLevel=5
LogPath=/var/log
LogType=Info Trace Error Debug
I created few python function use to serialize the INI configuration into dictionary. But there are some assumption to make. Assume that the comment of INI is start with char ‘#’. python dictionary do not takes in comments, because comment is not configuration. But what if after I change the configurations in dictionary and want to serialize back to INI file with the original comments stayed in as well? Yes you can remain the comments with the set of python functions I wrote.
Lets look at what function I have.
grep (str_list,pattern,neg=False): is my internal function to filter element in string list (first param).
ParseConfig (name=None): put the INI config filename as param, dictionary object will be returned.
ConfigTemplate (name=None): The construct the INI structure in another dictionary, storing the Section Name as well as your comments.
ConfigWrite (template=[],config=[],filename=”"): This function is to serialize back the python dictionary back to INI file. First param takes in the template dictionary object, second takes in configuration dictionary object.
Lets us look at all functions definition as well as the examples: ParseConfig.py
#/usr/bin/env python
import sys,os,datetime,time,re,string
from StringIO import StringIO
GREP_NEGATIVE=True
def grep (str_list,pattern,neg=False):
"""grep() will return list of match case.
Param: str_list - must be a list of string, each element in list is a new line
can use .split('\n') to obtain list from mutiple line of string
Param: pattern - re pattern can be composed by re.compile()"""
sres=[] #empty list
for s in str_list:
r=re.search(pattern,s,re.VERBOSE)
if r and neg==False:
sres.append(s)
elif (not r) and neg==True:
sres.append(s)
return sres
def ParseConfig (name=None):
global GREP_NEGATIVE
""" Parsing config file to this function, will serialized to dictionary
@name = filename
@return = dictionary"""
configdict={}
loglist=[]
while True:
try:
f = open(name,"r")
except IOError:
print "Err ",name,"not exist"
return None
pass
else:
break
try:
for line in f:
#strip all the whitespaces and write all lines to list.
loglist.append(line.strip(string.whitespace))
finally:
f.close()
# filter out the comment
loglist=grep(loglist,"^\#",GREP_NEGATIVE)
# make a dictionary
xL=[] #current L
itemdict={}
for item in loglist:
L=grep([item],"^\[.*\]$") # section
if L:
xL=[L[0].lstrip("[").rstrip("]")]
itemdict={}
#print xL
else: # items?
if len(xL)>0:
if item:
#split index and values.
iL=item.split("=")
#replace all '\t' to " " in values
iL[1]=string.replace(iL[1],"\t"," ")
# split the values into list
iiL=iL[1].strip(string.whitespace).split(" ")
real_list=[]
for item in iiL:
# read each value in the list, if got something append to the real_list
if len(item.strip(string.whitespace)) is not 0:
real_list.append(item.strip(string.whitespace))
# create another dict into the section
itemdict[iL[0].strip(string.whitespace)]=real_list
configdict[xL[0]]=itemdict
return configdict
pass
def ConfigTemplate (name=None):
try:
f=open(name,"r")
except IOError:
return None
loglist=[]
try:
for line in f:
#strip all the whitespaces and write all lines to list.
theline = line.strip(string.whitespace)
loglist.append(theline)
finally:
f.close()
loglist=grep(loglist,"^\#|^\[")
if len(loglist) is 0:
loglist = None
return loglist
def ConfigWrite (template=[],config=[],filename=""):
global DebugDupConfigWrite
if len(template) is 0 or len(config) is 0 or filename is "":
return False
try:
f = open(filename,"w")
for line in template:
r=re.search("^\#",line,re.VERBOSE)
if r:
f.write(line + "\n")
j=re.search("^\[",line,re.VERBOSE)
if j:
f.write(line + "\n")
# get all section line up
section_name = line.strip(string.whitespace).lstrip("[").rstrip("]")
if config.has_key(section_name):
sec_dict = config[section_name]
#
element_list=[]
for element in sec_dict:
element_list.append(element)
element_list.sort()
for element in element_list:
# index = values....
#print element, sec_dict[element]
f.write(element + " = " + "\t".join(sec_dict[element]) + "\n")
f.write("\n")
else:
pass
#f.write("CAN'T FIND THE ELEMENTS in section[%s]! DATA CORRUPTED.\n" % section_name)
pass # end if j
pass # end for line
f.close()
return True
except:
return False
# sample calling
myDict = ParseConfig ("config.ini")
template = ConfigTemplate ("config.ini")
ConfigWrite(template,myDict,"test.ini")
print "COMPLETE DICTIONARY"
print myDict
print "ALL TAGS"
for c in myDict:
print " ",c
print ""
print "ALL ITEM IN 'GENERAL'"
for d in myDict["GENERAL"]:
print " ",d
print ""
print "ALL ITEM IN 'LOG'"
for d in myDict["LOG"]:
print " ",d
print ""
print "DIRECT ACCESS 'LOG's LOGTYPE'"
print myDict["LOG"]["LogType"]
print "SO, YOU CAN SEE THAT IS THE LIST, IT ITERATE the LIST"
for e in myDict["LOG"]["LogType"]:
print " ",e
print "DIRECT ACCESS 'LOG's LOGTYPE 2nd value'"
print "second value is ",myDict["LOG"]["LogType"][1]
I hope my example is straight forward for you to understand how to use it, wish you enjoy python scripting :)
Live Chat!







September 14th, 2009 at 9:37 pm
Tech Blog Link Request - http://www.adamsinfo.com
Hi
For leveraging traffic from the internet, I have manually collected a list of quality blogs with whom I am interested in getting associated.
I liked your blog and i’m interested in having my blog’s text link in your blog roll.
Please let me know your interest in this association and then we can move towards next step.
Sincerely,
Webmaster
Adamsinfo.com
vibha@apnicsolutions.com