Python标准库中的configparser模块,是专门用来读写配置文件的模块。我们常使用后缀为ini的文件来表示配置文件,据说ini配置文件最早出现在Win系统中,是Initialization File的缩写 ,现在已成为一个比较通用的格式。
configparser支持的配置文件格式
配置文件是一个文本文件,文件内有用方括号[]括起来的区域,称为section,以及区域内的key/value对。section的名称是case sensitive的,即大小写相关;而key的名称则大小写无关。
key/value使用等号(=)或者冒号(:)进行分割,key和value都是string,如果需要别的类型,要自己在代码中进行转换。因为都是string,key和value的中间可以有空格,但是两边的空格则会被忽略。value还可以多行,换行后要用前置的空格来表示这是一个换行处。
在ini配置文件中,还可以有注释,以#或;开头的行,都是注释。在解析的时候,注释会被直接忽略掉。
下面是一个Python configparser模块支持的ini配置文件的例子:
# file name: example.ini
[DEFAULT]
item1 = 1
ITEM2 = 2
Item3 = 3
item4=4
item5 : 5
item6:6
item 7 = 7 7 7
port = 12345
; this is also comments
sth =
[Server]
server = py.maixj.net
#port = 12345
name = i don't want to
tell you my name, haha...
[Web]
ITEM2=222.222
web server = apache
alternative = nginx
用configparser模块读配置文件
用configparser模块读配置文件,就像读dict对象的内容一样简单清晰。我用下面这段代码来说明如何读配置文件:
>>> import configparser
>>> config = configparser.ConfigParser()
>>> config.read('example.ini')
['example.ini']
>>> config.sections()
['Server', 'Web']
>>> config['Server']['port']
'12345'
首先创建一个ConfigParser对象,然后读取ini配置文件(文件后缀其实无所谓,只要是符合规则的文本文件都可以成功读取)。config.sections() 函数返回配置文件中所有的区域,可以看到,DEFAULT区域是不会显示出来的(下文解释)。然后就是读取配置,config['Server']['port'] 就是读取Server区域port的配置值,Server区域没有配置port,因此这个值来自DEFAULT区域。
配置文件中的DEFAULT区域
上文的example.ini配置文件,有一个DEFAULT区域,这个区域有一点点特别。顾名思义,DEFAULT区域保存了配置项的默认值。比如上面的代码,我们去获取Server区域的port,看上面的ini配置文件,Server区域没有直接配置port,但是DEFAULT区域有,这时代码返回的port值,就来自DEFAULT区域。而且,DEFAULT区域不会出现在section list中。
Web区域的item2(key大小写无关哦)有定义,因此其值会覆盖DEFAULT区域的值:
>>> config['Web']['item2']
'222.222'
>>> config['Web']['Item2']
'222.222'
>>> config['Web']['ITEM2']
'222.222'
在看一段测试代码,这段代码显示了分隔符,key和value中的空格,对行value等特性的支持,注意sth配置项,没有值,读取它得到的是要给空字符串。
>>> config['Web']['item4']
'4'
>>> config['Web']['item5']
'5'
>>> config['Web']['item6']
'6'
>>> config['Web']['item 7']
'7 7 7'
>>> config['Web']['web server']
'apache'
>>> config['Server']['name']
"i don't want to\ntell you my name, haha..."
>>> config['Server']['sth']
''
Server区域中的name配置项是多行的,获取到的值中间有个换行符,这个细节要注意。
遍历section的所有配置项
从上文中的示例代码可以看出,访问某个具体的配置项,与访问Python的dict对象是一摸一样的。我们可以通过下面的代码,来遍历section,找出其所有的配置项的key,然后自然也能得到对应的value:
>>> for k in config['Web']:
... print(k, '-->', config['Web'][k])
...
item2 --> 222.222
web server --> apache
alternative --> nginx
item1 --> 1
item3 --> 3
item4 --> 4
item5 --> 5
item6 --> 6
item 7 --> 7 7 7
port --> 12345
DEFAULT区域中的配置项,遍历Web区域的时候,就显示出来了。
配置项的数据类型
前文已经有所叙述,配置文件中的数据默认都是string,如果需要其它类型,要自己在代码中转化。请看下面的示例代码:
>>> type(config['Web']['item2'])
>>> float(config['Web']['item2'])
222.222
>>> type(config['Web']['item1'])
>>> int(config['Web']['item1'])
1
由于上面的这种类型转换非常普遍,configparser模块还提供了几个很顺手的函数来专门处理这种转换。有 get() ,getint() ,getfloat() ,getboolean() 这四个。get()函数是通用的,读出来的是string。
>>> config.get('Web','web server')
'apache'
>>> config.getint('Web','item5')
5
>>> config.getfloat('Web','item2')
222.222
>>> config.getboolean('Web','item1')
True
注意getboolean()函数,配置项的值如果是 1, yes, on, true,使用getboolean()函数读出来的就是True;配置项的值如果是 0,no,off,false,读出来的就是False。
另一种读取配置数据的方式
下面展示另外一种读取配置项的代码写法,将section指向一个单独的变量,同样使用get()函数来读取配置的值:
>>> configWeb = config['Web']
>>> configWeb.get('web server')
'apache'
>>> configWeb.getint('port')
12345
>>> configWeb['alternative']
'nginx'
Fallback值
不太好翻译fallback这个单词,很多时候,我们阅读英文技术文献,翻译都会造成理解的偏差和混乱,因此我更喜欢直接使用原文。fallback这个词,查字典,有应急的意思。
Fallback值很好理解,就是在读取配置项的值的时候,如果某个配置项不存在(就是没有配置),fallback值提供了其默认的值。
>>> configWeb.get('site') is None
>>> True
>>> configWeb.get('site','py.maixj.net')
'py.maixj.net'
site不存在于example.ini配置文件中,通过fallback值来提供默认值,而如果没有fallback值,get函数的返回是None。对于不存在的配置项,使用get函数更安全,不会出现KeyError异常。
如果配置项存在,不管是存在于DEFAULT区域,还是别的区域,也不管有没有值(=号后面为空,就是没有值),fallback值都会失效。看下面的代码:
>>> configWeb.get('item2','abcde')
'222.222'
>>> configWeb.get('web server','abcde')
'apache'
>>> configWeb.get('sth','abcde')
''
用configparser模块写配置文件
一般情况下,我们都是直接用文本编辑器编写配置文件,不过有的时候,也需要用代码来生成配置文件。除了可以读取配置文件,configparser模块也支持用代码生成一个符合规则的配置文件。就像读取一样,写一个配置文件也跟操作dict对象一样。
>>> import configparser
>>> config = configparser.ConfigParser()
>>> config['DEFAULT'] = {'A':1,'B':2,'C':3}
>>> config['Server'] = {}
>>> config['Server']['A'] = '5'
>>> config['Server']['B'] = '6'
>>> config['Server']['D'] = '8'
>>> with open('anotest.ini','w') as inifile:
... config.write(inifile)
以上代码生成的anotest.ini文件的内容如下:
xinlin@ubuntu:~/repos/sendslip$ cat anotest.ini
[DEFAULT]
a = 1
b = 2
c = 3
[Server]
a = 5
b = 6
d = 8
自动写配置文件,应用场景应该是不需要用户直接编写配置文件的应用,用户查看和修改配置文件,都要通过一个(很可能是)GUI界面。这个时候的配置文件,内中的注释就没有意义了,只要程序能读懂就OK。
我们再看看add_section和remove_section函数的用法,还有一个options函数:
>>> import configparser
>>> config = configparser.ConfigParser()
>>> config.add_section('Server')
>>> config['Server']['addr'] = '1.2.3.4'
>>> config['Server']['domain'] = 'py.maixj.net'
>>> config['Server']['log'] = 'on'
>>> config.sections()
['Server']
>>> config.options('Server')
['addr', 'domain', 'log']
>>> config.remove_section('Server')
True
>>> config.sections()
[]
以上内容,基本已经将configparser模块如何读写配置文件说清除了,还有一些高级用法,以后再继续。
-- EOF --