Python版本:Python 3.6.1
这个模块提供了基本配置方案,你可以在 Python 语言中清楚的编写配置文件(ini 文件),然后在终端中轻松配置。
1. 快速入门
让我们看一个非常基础的配置文件,如下所示:
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = hg
[topsecret.server.com]
Port = 50022
ForwardX11 = no
ini 文件的具体结构我们在下面的章节中描述。本质上,该文件有一个 sections 和一些键值对组成。 configparser 类可以读写这些文件。我们可以通过下面的程序来编写这个配置文件。
import configparser
config = configparser.ConfigParser()
config['DEFAULT'] = {'ServerAliveInterval': '45',
'Compression': 'yes',
'CompressionLevel': '9'}
config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg'
config['topsecret.server.com'] = {}
topsecret = config['topsecret.server.com']
topsecret['Port'] = '50022'
topsecret['ForwardX11'] = 'no'
config['DEFAULT']['ForwardX11'] = 'yes'
with open('example.ini', 'w') as configfile:
config.write(configfile)
正如你所看到的,我们可以像字典一样来配置解析器。现在我们已经创建并保存了一个配置文件,接下来让我们读取这个文件。
import configparser
config = configparser.ConfigParser()
config.read('example.ini')
print(config.sections())
if 'bitbucket.org' in config:
print(True)
if 'bytebong.com' in config:
print(True)
print(config['bitbucket.org']['User'])
print(config['DEFAULT']['Compression'])
topsecret = config['topsecret.server.com']
print(topsecret['ForwardX11'])
print(topsecret['Port'])
for key in config['bitbucket.org']: print(key)
print(config['bitbucket.org']['ForwardX11'])
正如我们在上面看到的,API设计非常简单。其中,最有特色的一个 section 是 DEFAULT
部分,它为所有其他 section 提供默认值。还要注意一点,section 中的键值不区分大小写,并且存储在小写中。
2. 支持的数据类型
配置解析器总是在配置文件中以字符串的形式存储数据。这就意味着,如果你需要使用其他的数据类型,那么你应该如下操作:
>>> int(topsecret['Port'])
50022
>>> float(topsecret['CompressionLevel'])
9.0
然而,提取布尔值并不是那么简单。如果我们通过 bool()
函数去提取布尔值,那么 bool('False')
值依然是 True
。所有,配置解析器也提供了 getboolean()
函数来提取布尔值。这个方法是不区分大小写的,并且能区分 yes/no
,on/off
,1/0
等二分类值。比如,
>>> topsecret.getboolean('ForwardX11')
False
>>> config['bitbucket.org'].getboolean('ForwardX11')
True
>>> config.getboolean('bitbucket.org', 'Compression')
True
除了提供 getboolean()
函数,配置解析器还提供了 getint()
和 getfloat()
方法,但是这两个方法很少使用,因为我们使用 int()
和 float()
方法就可以达到这个效果。
3. 回退值
作为一个字典,你可以使用 get()
方法来提供缺省值:
>>> topsecret.get('Port')
'50022'
>>> topsecret.get('CompressionLevel')
'9'
>>> topsecret.get('Cipher')
>>> topsecret.get('Cipher', '3des-cbc')
'3des-cbc'
请注意,默认值的优先级高于回退值。例如,在我们的例子中 compressionlevel
已经在 DEFAULT
部分中指定。如果我们从 topsecret.server.com
部分中尝试得到这个值,那么我们得到的值总是默认值,尽管你指定一个回退值。
>>> topsecret.get('CompressionLevel', '3')
'9'
还有一点需要注意的是,get()
方法提供了一个定制的,更加复杂的界面,并且保持向后兼容性。使用此方法时,可以通过回退关键字仅提供回退值:
>>> config.get('bitbucket.org', 'monster',
... fallback='No such things as monsters')
'No such things as monsters'
同样的回退参数可以使用 getint()
,getfloat()
和 getboolean()
方法,例如:
>>> 'BatchMode' in topsecret
False
>>> topsecret.getboolean('BatchMode', fallback=True)
True
>>> config['DEFAULT']['BatchMode'] = 'no'
>>> topsecret.getboolean('BatchMode', fallback=True)
False
4. INI 文件结构
配置文件由很多的 section 组成,每个 section 的头部都是由一个 [section] 标头一你到,接着是一些键值对组成,键值对由特定字符串分隔,比如,=
或者 :
。默认情况下,section 是区分大小写的,但是键是不区分的。键值对的前导空格和尾部空格都是可以自动删除的。值也可以跨越多行,只要它们缩进的深度比值得第一行要深就行了。根据解析模式,空白行会被作为多值部分或忽略。
配置文件可以包括注释,以特定的字符 #
或者 ;
开始。注释可能会出现在一条空行上,也可能会缩进。
例如下面的文件:
[Simple Values]
key=value
spaces in keys=allowed
spaces in values=allowed as well
spaces around the delimiter = obviously
you can also use : to delimit keys from values
[All Values Are Strings]
values like this: 1000000
or this: 3.14159265359
are they treated as numbers? : no
integers, floats and booleans are held as: strings
can use the API to get converted values directly: true
[Multiline Values]
chorus: I'm a lumberjack, and I'm okay
I sleep all night and I work all day
[You can use comments]
# like this
; or this
# By default only in an empty line.
# Inline comments can be harmful because they prevent users
# from using the delimiting characters as parts of values.
# That being said, this can be customized.
[Sections Can Be Indented]
can_values_be_as_well = True
does_that_mean_anything_special = False
purpose = formatting for readability
multiline_values = are
handled just fine as
long as they are indented
deeper than the first line
of a value
# Did I mention we can indent comments, too?
5. 插补值
配置解析器有一个核心的功能,ConfigParser 支持插值。这意味着配置文件中的值可以通过预处理得到。
class configparser.BasicInterpolation
配置文件是用 ConfigParser 来实现默认值。它使值包含格式字符串,该字符串可以引用同一个 section 中的其他值,也可以是默认 section 中的其它值。而且,我们可以在初始化的时候提供额外的默认值。
比如:
[Paths]
home_dir: /Users
my_dir: %(home_dir)s/lumberjack
my_pictures: %(my_dir)s/Pictures
在上面这个例子中,插值设置在 BasicInterpolation() 模块中,它能解决 %(home_dir)s 变量赋值的问题,这个例子中该值为 /Users。再比如,%(my_dir)s 变量在例子中为 /Users/lumberjack。
我们可以通过以下程序来测试我们编写的配置文件。
import configparser
config = configparser.ConfigParser()
config._interpolation = configparser.BasicInterpolation()
config.read('example.ini')
print(config.get('Paths', 'my_dir'))
class configparser.ExtendedInterpolation
插值实现更高级的语法替代处理程序,例如这种形式 zc.buildout 。我们需要使用扩展类型的插值实现 ${section: option}。为了方便起见,如果省略了 section,那么我们默认就是当前的 section。
例如,在基本插值中指定的配置,将使用扩展插值来进行配置:
[Paths]
home_dir: /Users
my_dir: ${home_dir}/lumberjack
my_pictures: ${my_dir}/Pictures
当然其它部分的 section 也可以被取出来:
[Common]
home_dir: /Users
library_dir: /Library
system_dir: /System
macports_dir: /opt/local
[Frameworks]
Python: 3.2
path: ${Common:system_dir}/Library/Frameworks/
[Arthur]
nickname: Two Sheds
last_name: Jackson
my_dir: ${Common:home_dir}/twosheds
my_pictures: ${my_dir}/Pictures
python_dir: ${Frameworks:path}/Python/Versions/${Frameworks:Python}
请注意,当我们使用高级插值的时候,我们需要使用以下语句来进行配置:
config = configparser.ConfigParser()
config._interpolation = configparser.ExtendedInterpolation()
我们对上述配置文件的读取程序如下:
import configparser
config = configparser.ConfigParser()
config._interpolation = configparser.ExtendedInterpolation()
config.read('example.ini')
print(config.get('Frameworks', 'path'))
print(config.get('Arthur', 'python_dir'))
6. 传统的 API 例子
主要是考虑到向后兼容的问题,configparser 还提供了传统的 API 形式,get
函数和 set
函数。虽然这种方法非常有效,但是对于新项目而言,我们还是希望可以直接在配置文件中书写配置信息。
写入配置文件的实例:
import configparser
config = configparser.RawConfigParser()
# Please note that using RawConfigParser's set functions, you can assign
# non-string values to keys internally, but will receive an error when
# attempting to write to a file or when you get it in non-raw mode. Setting
# values using the mapping protocol or ConfigParser's set() does not allow
# such assignments to take place.
config.add_section('Section1')
config.set('Section1', 'an_int', '15')
config.set('Section1', 'a_bool', 'true')
config.set('Section1', 'a_float', '3.1415')
config.set('Section1', 'baz', 'fun')
config.set('Section1', 'bar', 'Python')
config.set('Section1', 'foo', '%(bar)s is %(baz)s!')
# Writing our configuration file to 'example.cfg'
with open('example.cfg', 'w') as configfile:
config.write(configfile)
那么,接下来我们来读取这个配置文件:
import configparser
config = configparser.RawConfigParser()
#config._interpolation = configparser.ExtendedInterpolation()
config._interpolation = configparser.BasicInterpolation()
config.read('example.cfg')
# getfloat() raises an exception if the value is not a float
# getint() and getboolean() also do this for their respective types
a_float = config.getfloat('Section1', 'a_float')
an_int = config.getint('Section1', 'an_int')
print(a_float + an_int)
print(config.get('Section1', 'foo'))
# Notice that the next output does not interpolate '%(bar)s' or '%(baz)s'.
# This is because we are using a RawConfigParser().
if config.getboolean('Section1', 'a_bool'):
print(config.get('Section1', 'foo'))