2008年7月1日 星期二

Python Read/Write INI File




首先我們定義INI Configuration File:(長什麼樣)

[Section1]
Key1=Value1
Key2=Value2

[Section2]
Key1=Value1
Key2=Value2


再來利用Python原本的ConfigParser
然後包了一個INIFile.py出來
但是在測試之後,發覺這個ConfigParser default處理Key這個值時,
是全轉小寫,但又說可以利用
雖然說可以利用optionxform丟 str() 進去,讓它不轉…
幾經測試,看了source code(ConfigParser.py),還是一樣,
我進去看了一下那段:
def optionxform(self, optionstr):
return optionstr.lower()

看到了嗎?那個是Default怎麼丟,都給你lower string...
所以只有好自己改code,另存一個MyConfigParser.py
變下面這段:
def optionxform(self, optionstr):
if ( self._bCaseSensitive ) :
return optionstr
else:
return optionstr.lower()

# 加一段在set case sensitive 的 code
class ConfigParser(RawConfigParser):

def setCaseSensitive(self, bCaseSensitive):
self._bCaseSensitive = bCaseSensitive


再來就是我的INIFile.py:
#!/usr/bin/env python
import sys
import os
import MyConfigParser

class INIOperator:
#def __init__(self):
#self.filename
#self.config
def OpenINIFile(self,strINIFile, bCaseSensitive = True):
if ( False == os.path.isfile(strINIFile) ):
return False
self.config = MyConfigParser.ConfigParser()
self.config.setCaseSensitive( bCaseSensitive )
if ( False == self.config.readfp(open(strINIFile)) ):
return False
return True

def GetSectionItems(self, strSection):
return self.config.items(strSection)

def GetSectionOptions(self, strSection):
return self.config.options(strSection)

def GetSections(self):
return self.config.sections() ;

def GetValue(self, strSection, strKey):
if ( True == self.config.has_section(strSection) ):
if ( True == self.config.has_option(strSection,strKey) ):
return self.config.get(strSection, strKey)
return None

def AddSection(self, strSection):
if ( False == self.config.has_section(strSection) ):
self.config.add_section(strSection)

def RemoveSection(self, strSection):
if ( True == self.config.has_section(strSection) ):
self.config.remove_section(strSection)

def SetValue(self, strSection, strKey, strValue):
self.AddSection(strSection)
self.config.set(strSection, strKey, strValue)

def RemoveOption(self, strSection, strKey):
if ( True == self.config.has_section(strSection) ):
if ( True == self.config.has_option(strSection,strKey) ):
self.config.remove_option(strSection, strKey)

def WriteINIFile(self,strINIFile):
if ( False == self.config.write(open(strINIFile,'w')) ):
return False
return True


import re
import string

class IniFile:
_section = re.compile(r'^\[(.*)\]\s*')
_option = re.compile(r'^([^\s]*)\s*=\s*(.*)$')

def __init__(self, fn):
self.filename = fn
self._data = {}

# Parse the .ini file
f = file(fn)
sect = ""
for line in f:
line = string.strip(line)
if line == "" or line[0] == ';':
continue
matchObj = self._section.match(line)
if matchObj != None:
#sect = string.upper(matchObj.group(1))
sect = str(matchObj.group(1))
if not self._data.has_key(sect):
self._data[sect] = {}
self._data[sect]['_values_'] = []
elif sect:
matchObj = self._option.match(line)
if matchObj != None:
opt, val = matchObj.group(1, 2)
self._data[sect][str(opt)] = val
else:
self._data[sect]['_values_'].append(line)
f.close()
del f

def items(self):
return self._data.items()
def __getitem__(self,x):
return self._data[x]
def values(self):
return self._data.values()
def __len__( self ):
return len(self._data)
def __repr__(self):
return 'self._data'
def __str__(self):
return 'self._data'
def keys(self):
return self._data.keys()
def has_key(self,x):
return self._data.has_key(x)



INIOperator才是最後要用的…
至於IniFile,是當初找到,測試用的…

再放一段測試的program:
#!/usr/bin/env python
'''
from INIFile import *

ini = IniFile('AU.ini.txt')
value = ini['AU']['AUServer']
print value

exit(0)
'''
import INIFile

# Declare INIFile Object
ini = INIFile.INIOperator()

# Open INIFile
# OpenINIFile( filename , bCaseSensitive )
if ( False == ini.OpenINIFile('AU.ini.txt', True) ): # open file with String Case Sensitive operation
print "Open INI File: " + strINIFile + " Failed!\n"
else:
# Get Section list
SectionList = ini.GetSections()
print SectionList

# Get All Keys in Section
OptionList = ini.GetSectionOptions("AU")
for optItem in OptionList:
print "%s\n" % str(optItem)

# Get All Item(Key=>Value pair) in Section
ItemList = ini.GetSectionItems("AU")
for strItem in ItemList:
print "%s\n" % str(strItem)

# Get Value in [Section]->Key
Value = ini.GetValue("AU", "Test")
if ( Value == None ):
print "No value in [AU]->'Test'\n"

# Set/Update [Section]->Key to Value
'''
AUServer=1.1.1.1
ProxyServer=2.2.2.2
Port=3333
UseProxy=1
UseSocks4=1
ProxyUsername=user
ProxyPassword=xxx (MUST be encrypted)
'''
ini.SetValue("AU", "AUServer", "1.1.1.1")
ini.SetValue("AU", "ProxyServer", "2.2.2.2")
ini.SetValue("AU", "Port", "3333")
ini.SetValue("AU", "UseProxy", "1")
ini.SetValue("AU", "UseSocks4", "1")
ini.SetValue("AU", "ProxyUsername", "Username")
ini.SetValue("AU", "ProxyPassword", "xxxxx")
if ( False == ini.WriteINIFile('AU.ini') ):
print "Write INI Setting To :" + strINIFile + " Failed!\n"

# Open again to check the value
ini.OpenINIFile('AU.ini', True) # open file with String Case Sensitive operation
# Get All Item(Key=>Value pair) in Section
ItemList = ini.GetSectionItems("AU")
for strItem in ItemList:
print "%s\n" % str(strItem)



留底…希望要用的可以參考…
另外~~
ConfigParser的Option 對應到我的Key
其他都沒什麼不同、只是另外包一層(多此一舉)~~~其實會用的,就直接用了
但還要一些防呆…(也許也不用)~~~
等開始寫時,就可能拿掉這層wrapper也不一定~~~

2 則留言:

馬克 提到...

其實關於lower這段,我也不知是不是有其他方法給它overwrite掉…
可能得再看看其他高手的code吧!
我想我的能力就是改成支援我想要的囉…

馬克 提到...

import ConfigParser
if ( True == bCaseSensitive ):
config.optionxform = str



簡化到不行,原來是我不會用ConfigParser...

要這樣指定啊…
我還以為是 config.optionxform(str) 咧~~~難怪一直試不出來…
我真是遜啊…