Serialize INI configuration to python dictionary

August 30th, 2009 mysurface Posted in Developer, python | Hits: 229859 | 17 Comments »

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 :)

17 Responses to “Serialize INI configuration to python dictionary”

  1. 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

  2. I just wanted to say thanks for providing an awesome site with straight up easily digestable Linux commands. This site has been an absolute godsend to me over the last few days. Moving from Windows to Linux environment was daunting but your site proved to be the only resource I actually needed in the end! Thanks so much guys, keep up the good work :)

    Chris.

  3. Nice post. I study one thing more difficult on completely different blogs everyday. It will all the time be stimulating to read content material from other writers and apply somewhat something from their store. I’d desire to make use of some with the content material on my blog whether you don’t mind. Natually I’ll offer you a link on your internet blog. Thanks for sharing.

  4. Pretty nice post. I just stumbled upon your blog and wanted to say that I have really enjoyed browsing your blog posts. In any case I’ll be subscribing to your feed and I hope you write again soon! cheap shirt wholesale

  5. You´ve got a secret admirer would you please email me with subject

  6. I loved as much as you will receive carried out right here. The sketch is tasteful, your authored material stylish. nonetheless, you command get got an edginess over that you wish be delivering the following. unwell unquestionably come more formerly again as exactly the same nearly very often inside case you shield this hike.

  7. Good day! I could have sworn I’ve been to this website before but after browsing through some of the post I realized it’s new to me. Anyways, I’m definitely delighted I found it and I’ll be book-marking and checking back often!

  8. I undoubtedly did not realize that. Learnt something new today! Thanks for that.

  9. I am impressed, I have to say. Really rarely do I see a blog that’s both educational and entertaining, and let me tell you, you have hit the nail on the head. Your blog is outstanding; the issue is something that not a lot of people are speaking intelligently about. I am very happy that I stumbled across this in my search for something relating to it.

  10. The sleeping fox catches no poultry

  11. Please tell me it worked right? I dont desire to sumit it once more if i don’t have to! Either the blog glitced out or i am an idiot, the second selection doesnt surprise me lol. thanks for a excellent blog!

  12. A person specifically lend a hand to make seriously content I might express. This can be the first time I actually seen your online site and so considerably? I personally surprised with the investigation you made to generate this particular submit remarkable. Excellent task!

  13. Salut Fred, Merci pour ta liste de site de streaming, moi je regarde lmes films sur ou surils
    ont toujours les derniers films en streaming
    gratuit avec en plus une interface sympa, il parait que c’est les anciens de fedbac qui ont fonde ces websites webs.

    Also visit my web-site – watch Lucy online Free

  14. obviously like your website however you need to take a look at
    the spelling on several of your posts. Several of
    them are rife with spelling problems and I in finding it very troublesome to tell the truth on the other hand I’ll surely come again again.

  15. Además puede utilizar su tarjeta de memoria para trabajar en un proyecto en varios ordenadores al unísono.

  16. Oh my goodness! Impressive article dude! Thanks, However I am
    encountering problems with your RSS. I don’t know
    the reason why I can’t join it. Is there anybody else getting similar
    RSS problems? Anyone who knows the solution will you kindly respond?
    Thanks!!

  17. From the giver’s point of view this is quite encouraging because it is not merely a gift that is
    liked and remembered but it is also the
    brand name of the company that is recollected with every use.
    Outdoor ads reach the potential customers and
    clients in a cost efficient way. Songs submission is actually increased having blog postings.

Leave a Reply