×

Python的配置模块:configparser

96
chen_h
2017.07.20 11:01* 字数 1414

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/noon/off1/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'))

来源:docs.python.org

Python
Web note ad 1