configparser --- 設定檔剖析器¶
This module provides the ConfigParser class which implements a basic
configuration language which provides a structure similar to what's found in
Microsoft Windows INI files. You can use this to write Python programs which
can be customized by end users easily.
備註
This library does not interpret or write the value-type prefixes used in the Windows Registry extended version of INI syntax.
也參考
tomllib模組TOML is a well-specified format for application configuration files. It is specifically designed to be an improved version of INI.
shlex模組Support for creating Unix shell-like mini-languages which can also be used for application configuration files.
json模組The
jsonmodule implements a subset of JavaScript syntax which is sometimes used for configuration, but does not support comments.
Quick Start¶
Let's take a very basic configuration file that looks like this:
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[forge.example]
User = hg
[topsecret.server.example]
Port = 50022
ForwardX11 = no
The structure of INI files is described in the following section. Essentially, the file
consists of sections, each of which contains keys with values.
configparser classes can read and write such files. Let's start by
creating the above configuration file programmatically.
>>> import configparser
>>> config = configparser.ConfigParser()
>>> config['DEFAULT'] = {'ServerAliveInterval': '45',
... 'Compression': 'yes',
... 'CompressionLevel': '9'}
>>> config['forge.example'] = {}
>>> config['forge.example']['User'] = 'hg'
>>> config['topsecret.server.example'] = {}
>>> topsecret = config['topsecret.server.example']
>>> topsecret['Port'] = '50022' # mutates the parser
>>> topsecret['ForwardX11'] = 'no' # same here
>>> config['DEFAULT']['ForwardX11'] = 'yes'
>>> with open('example.ini', 'w') as configfile:
... config.write(configfile)
...
As you can see, we can treat a config parser much like a dictionary. There are differences, outlined later, but the behavior is very close to what you would expect from a dictionary.
Now that we have created and saved a configuration file, let's read it back and explore the data it holds.
>>> config = configparser.ConfigParser()
>>> config.sections()
[]
>>> config.read('example.ini')
['example.ini']
>>> config.sections()
['forge.example', 'topsecret.server.example']
>>> 'forge.example' in config
True
>>> 'python.org' in config
False
>>> config['forge.example']['User']
'hg'
>>> config['DEFAULT']['Compression']
'yes'
>>> topsecret = config['topsecret.server.example']
>>> topsecret['ForwardX11']
'no'
>>> topsecret['Port']
'50022'
>>> for key in config['forge.example']:
... print(key)
user
compressionlevel
serveraliveinterval
compression
forwardx11
>>> config['forge.example']['ForwardX11']
'yes'
As we can see above, the API is pretty straightforward. The only bit of magic
involves the DEFAULT section which provides default values for all other
sections [1]. Note also that keys in sections are
case-insensitive and stored in lowercase [1].
It is possible to read several configurations into a single
ConfigParser, where the most recently added configuration has the
highest priority. Any conflicting keys are taken from the more recent
configuration while the previously existing keys are retained. The example
below reads in an override.ini file, which will override any conflicting
keys from the example.ini file.
[DEFAULT]
ServerAliveInterval = -1
>>> config_override = configparser.ConfigParser()
>>> config_override['DEFAULT'] = {'ServerAliveInterval': '-1'}
>>> with open('override.ini', 'w') as configfile:
... config_override.write(configfile)
...
>>> config_override = configparser.ConfigParser()
>>> config_override.read(['example.ini', 'override.ini'])
['example.ini', 'override.ini']
>>> print(config_override.get('DEFAULT', 'ServerAliveInterval'))
-1
This behaviour is equivalent to a ConfigParser.read() call with several
files passed to the filenames parameter.
Supported Datatypes¶
Config parsers do not guess datatypes of values in configuration files, always storing them internally as strings. This means that if you need other datatypes, you should convert on your own:
>>> int(topsecret['Port'])
50022
>>> float(topsecret['CompressionLevel'])
9.0
Since this task is so common, config parsers provide a range of handy getter
methods to handle integers, floats and booleans. The last one is the most
interesting because simply passing the value to bool() would do no good
since bool('False') is still True. This is why config parsers also
provide getboolean(). This method is case-insensitive and
recognizes Boolean values from 'yes'/'no', 'on'/'off',
'true'/'false' and '1'/'0' [1]. For example:
>>> topsecret.getboolean('ForwardX11')
False
>>> config['forge.example'].getboolean('ForwardX11')
True
>>> config.getboolean('forge.example', 'Compression')
True
Apart from getboolean(), config parsers also
provide equivalent getint() and
getfloat() methods. You can register your own
converters and customize the provided ones. [1]
Fallback Values¶
As with a dictionary, you can use a section's get() method to
provide fallback values:
>>> topsecret.get('Port')
'50022'
>>> topsecret.get('CompressionLevel')
'9'
>>> topsecret.get('Cipher')
>>> topsecret.get('Cipher', '3des-cbc')
'3des-cbc'
Please note that default values have precedence over fallback values.
For instance, in our example the 'CompressionLevel' key was
specified only in the 'DEFAULT' section. If we try to get it from
the section 'topsecret.server.example', we will always get the default,
even if we specify a fallback:
>>> topsecret.get('CompressionLevel', '3')
'9'
One more thing to be aware of is that the parser-level get() method
provides a custom, more complex interface, maintained for backwards
compatibility. When using this method, a fallback value can be provided via
the fallback keyword-only argument:
>>> config.get('forge.example', 'monster',
... fallback='No such things as monsters')
'No such things as monsters'
The same fallback argument can be used with the
getint(), getfloat() and
getboolean() methods, for example:
>>> 'BatchMode' in topsecret
False
>>> topsecret.getboolean('BatchMode', fallback=True)
True
>>> config['DEFAULT']['BatchMode'] = 'no'
>>> topsecret.getboolean('BatchMode', fallback=True)
False
支援的 INI 檔案結構¶
A configuration file consists of sections, each led by a [section] header,
followed by key/value entries separated by a specific string (= or : by
default [1]). By default, section names are case sensitive but keys are not
[1]. Leading and trailing whitespace is removed from keys and values.
Values can be omitted if the parser is configured to allow it [1],
in which case the key/value delimiter may also be left
out. Values can also span multiple lines, as long as they are indented deeper
than the first line of the value. Depending on the parser's mode, blank lines
may be treated as parts of multiline values or ignored.
By default, a valid section name can be any string that does not contain '\n'.
To change this, see ConfigParser.SECTCRE.
The first section name may be omitted if the parser is configured to allow an
unnamed top level section with allow_unnamed_section=True. In this case,
the keys/values may be retrieved by UNNAMED_SECTION as in
config[UNNAMED_SECTION].
Configuration files may include comments, prefixed by specific
characters (# and ; by default [1]). Comments may appear on
their own on an otherwise empty line, possibly indented. [1]
舉例來說:
[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
[No Values]
key_without_value
empty string value here =
[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?
Unnamed Sections¶
The name of the first section (or unique) may be omitted and values
retrieved by the UNNAMED_SECTION attribute.
>>> config = """
... option = value
...
... [ Section 2 ]
... another = val
... """
>>> unnamed = configparser.ConfigParser(allow_unnamed_section=True)
>>> unnamed.read_string(config)
>>> unnamed.get(configparser.UNNAMED_SECTION, 'option')
'value'
Interpolation of values¶
On top of the core functionality, ConfigParser supports
interpolation. This means values can be preprocessed before returning them
from get() calls.
- class configparser.BasicInterpolation¶
The default implementation used by
ConfigParser. It enables values to contain format strings which refer to other values in the same section, or values in the special default section [1]. Additional default values can be provided on initialization.舉例來說:
[Paths] home_dir: /Users my_dir: %(home_dir)s/lumberjack my_pictures: %(my_dir)s/Pictures [Escape] # use a %% to escape the % sign (% is the only character that needs to be escaped): gain: 80%%
In the example above,
ConfigParserwith interpolation set toBasicInterpolation()would resolve%(home_dir)sto the value ofhome_dir(/Usersin this case).%(my_dir)sin effect would resolve to/Users/lumberjack. All interpolations are done on demand so keys used in the chain of references do not have to be specified in any specific order in the configuration file.With
interpolationset toNone, the parser would simply return%(my_dir)s/Picturesas the value ofmy_picturesand%(home_dir)s/lumberjackas the value ofmy_dir.
- class configparser.ExtendedInterpolation¶
An alternative handler for interpolation which implements a more advanced syntax, used for instance in
zc.buildout. Extended interpolation is using${section:option}to denote a value from a foreign section. Interpolation can span multiple levels. For convenience, if thesection:part is omitted, interpolation defaults to the current section (and possibly the default values from the special section).For example, the configuration specified above with basic interpolation, would look like this with extended interpolation:
[Paths] home_dir: /Users my_dir: ${home_dir}/lumberjack my_pictures: ${my_dir}/Pictures [Escape] # use a $$ to escape the $ sign ($ is the only character that needs to be escaped): cost: $$80
Values from other sections can be fetched as well:
[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}
Mapping Protocol Access¶
在 3.2 版被加入.
Mapping protocol access is a generic name for functionality that enables using
custom objects as if they were dictionaries. In case of configparser,
the mapping interface implementation is using the
parser['section']['option'] notation.
parser['section'] in particular returns a proxy for the section's data in
the parser. This means that the values are not copied but they are taken from
the original parser on demand. What's even more important is that when values
are changed on a section proxy, they are actually mutated in the original
parser.
configparser objects behave as close to actual dictionaries as possible.
The mapping interface is complete and adheres to the
MutableMapping ABC.
However, there are a few differences that should be taken into account:
By default, all keys in sections are accessible in a case-insensitive manner [1]. E.g.
for option in parser["section"]yields onlyoptionxform'ed option key names. This means lowercased keys by default. At the same time, for a section that holds the key'a', both expressions returnTrue:"a" in parser["section"] "A" in parser["section"]
All sections include
DEFAULTSECTvalues as well which means that.clear()on a section may not leave the section visibly empty. This is because default values cannot be deleted from the section (because technically they are not there). If they are overridden in the section, deleting causes the default value to be visible again. Trying to delete a default value causes aKeyError.DEFAULTSECT不能從剖析器中移除: