Python Config Parser
Config Parser
Config Parser is commonly used with Python applications to configure application settings. ConfigParser is included as a core package in Python. It is common to have multiple files: one for each OS and/or environment.
Creating a Config File
For starters, we can use ConfigParser to dynamically create a configuration file. The first step will involve importing ConfigParser and initializing the class.
config_file_create.py
from configparser import ConfigParser
config = ConfigParser()
These types of config files are divided into sections. In this example, we will setup three sections:
- settings
- db
- files
config_file_create.py
from configparser import ConfigParser
config = ConfigParser()
config['settings'] = {
'debug': 'true',
'secret_key': 'abc123',
'log_path': '/my_app/log'
}
config['db'] = {
'db_name': 'myapp_dev',
'db_host': 'localhost',
'db_port': '8889'
}
config['files'] = {
'use_cdn': 'false',
'images_path': '/my_app/images'
}
Now that we have our three sections with multiple options set in each one, we can now create the config file. Using a context manager to open the file, we can write it to an external file dev.ini
.
config_file_create.py
from configparser import ConfigParser
# ...
with open('./dev.ini', 'w') as f:
config.write(f)
We should now see the dev.ini
file in our local working directory with the following contents:
[settings]
debug = true
secret_key = abc123
log_path = /my_app/log
[db]
db_name = myapp_dev
db_host = localhost
db_port = 8889
[files]
use_cdn = false
images_path = /my_app/images
Now that we have successfully generated a config file, we can now read it.
Reading a Config File
Similar to the creation of the file, we will need to import ConfigParser and initialize the class.
from configparser import ConfigParser
config = ConfigParser()
Next we will need to read the file:
parser.read('dev.ini')
Once this variable is set, we can grab any of the settings in the file using the following methods:
sections
method will return a list of each sectionget
method will return a single option within a sectionoptions
method will list each available option in a section
The in
operator can be used to check if a section exists, returning a boolean value.
print(parser.sections()) # ['settings', 'db', 'files']
print(parser.get('settings', 'secret_key')) # abc123
print(parser.options('settings')) # ['debug', 'secret_key', 'log_path']
print('db' in parser) # True
When loading from a config file, all data types will be returned as strings. We could convert the data type using methods like int() or float(), however, ConfigParser has it’s own methods for handling this:
- getint()
- getfloat()
- getboolean()
Below, the parser is being used to get the database port. The getint() method is the preferred way. In addition, we can set a fallback parameter in case the value is not set in the config file, which is the case for db_default_port
.
print(parser.get('db', 'db_port'), type(parser.get('db', 'db_port'))) # 8889 <class 'str'>
print(int(parser.get('db', 'db_port'))) # 8889 (as int)
print(parser.getint('db', 'db_default_port', fallback=3306)) # 3306
Using the getboolean() method will work for any values that are truthy of falsey. In the config file, we have our settings debug option set to the string value ‘true’. The other string values that would have worked for this include: ‘1’, ‘yes’, and ‘on’. False values, on the other hand, include ‘0’, ‘no’, ‘false’, and ‘off’.
print(parser.getboolean('settings', 'debug', fallback=False)) # True
Using String Interpolation
String interpolation can be used to derive values from other settings. To show how this works, let’s add to our original create file:
from configparser import ConfigParser
# ...
config['settings'] = {
'debug': 'true',
'secret_key': 'abc123',
'log_path': '/my_app/log',
'python_version': '3',
'packages_path': '/usr/local'
}
# ...
config['files'] = {
'use_cdn': 'false',
'images_path': '/my_app/images',
'python_path': '${settings:packages_path}/bin/python${settings:python_version}'
}
# ...
We added the options python_version
and packages_path
to our settings section. Then, in the files section, we added our python_path
using values from the sections section. We can re-run this script, creating a new dev.ini
file.
We will also need to make edits in our read file. If we don’t tell the ConfigParser that there’s string interpolation, it will give us the raw string containing the brackets without substituting the real values. We need to import ExtendedInterpolation and pass it in to the ConfigParser class init method. Once we do that, we can get the python_path option with the correct value.
from configparser import ConfigParser, ExtendedInterpolation
parser = ConfigParser(interpolation=ExtendedInterpolation())
parser.read('dev.ini')
print(parser.get('files', 'python_path')) # /usr/local/bin/python3
Posted in python