Many programs require configuration. Most have a default configuration and many allow the user to adjust that configuration. There are many different types of configuration files. Some use text files while others use databases. Python has a standard library called configparser
that you can use to work with Microsoft Windows INI files.
In this tutorial, you will cover the following topics:
- An example INI file
- Creating a config file
- Editing a config file
- Reading a config file
By the end of this tutorial, you will be able to use INI configuration files programmatically with Python.
Let’s get started!
Example INI File
There are many examples of INI files on the Internet. You can find one over in the Mypy documentation. Mypy is a popular type checker for Python. Here is the mypy.ini
file that they use as an example:
# Global options: [mypy] warn_return_any = True warn_unused_configs = True # per-module options: [mypy-mycode.foo.*] disallow_untyped_defs = True [ypy-mycode.bar] warn_return_any = False [mypy-somelibrary] ignore_missing_imports = True
Sections are denoted by being placed inside square braces. Then, each section can have zero or more settings. In the next section, you will learn how to create this configuration file programmatically with Python.
Creating a Config File
The documentation for Python’s configparser
module is helpful. They tell you how to recreate an example INI file right in the documentation. Of course, their example is not the Mypy example above. Your job is a little bit harder as you need to be able to insert comments into your configuration, which isn’t covered in the documentation. Don’t worry. You’ll learn how to do that now!
Open up your Python editor and create a new file called create_config.py
. Then enter the following code:
# create_config.py import configparser config = configparser.ConfigParser(allow_no_value=True) config["mypy"] = {"warn_return_any": "True", "warn_unused_configs": "True",} config.set("mypy", "\n# Per-module options:") config["mypy-mycode.foo.*"] = {"disallow_untyped_defs": "True"} config["ypy-mycode.bar"] = {"warn_return_any": "False"} config["mypy-somelibrary"] = {"ignore_missing_imports": "True"} with open("custom_mypy.ini", "w") as config_file: config_file.write("# Global options:\n\n") config.write(config_file)
The documentation states that the allow_no_value parameter allows for including sections that do not have values. You need to add this to be able to add comments in the middle of a section to be added as well. Otherwise, you will get a TypeError.
To add entire sections, you use a dictionary-like interface. Each section is denoted by the key, and that section’s values are added by setting that key to another dictionary.
Once you finish creating each section and its contents, you can write the configuration file to disk. You open a file for writing, then write the first comment. Next, you use the config.write()
method to write the rest of the file.
Try running the code above; you should get the same INI file as the one at the beginning of this article.
Editing a Config File
The configparser
library makes editing your configuration files mostly painless. You will learn how to change a setting in the config file and add a new section to your pre-existing configuration.
Create a new file named edit_config.py
and add the following code to it:
# edit_config.py import configparser config = configparser.ConfigParser() config.read("custom_mypy.ini") # Change an item's value config.set("mypy-somelibrary", "ignore_missing_imports", "False") # Add a new section config["new-random-section"] = {"compressed": "True"} with open("modified_mypy.ini", "w") as config_file: config.write(config_file)
In this case, after create the ConfigParser()
instance, you call read()
to read the specified configuration file. Then you can set any value you want.
Unfortunately, you cannot use dictionary-like syntax to set values. Instead, you must use set()
which takes the following parameters:
- section– The name of the section.
- option– The option you wish to change.
- value– The new value you want to set.
Adding a new section works like it did when you created the initial sections in the last code example. You still use dictionary-like syntax where the new section is the key and the value is a dictionary of one or more settings to go in your section.
When you run this code, it will create an INI file with the following contents:
[mypy] warn_return_any = True warn_unused_configs = True [mypy-mycode.foo.*] disallow_untyped_defs = True [ypy-mycode.bar] warn_return_any = False [mypy-somelibrary] ignore_missing_imports = False [new-random-section] compressed = True
Good job! You’ve just learned how to modify an INI file with Python!
Now you are ready to learn about reading INI files.
Reading a Config File
You already caught a glimpse of how to read a configuration file in the previous section. The primary method is by calling the ConfigParser
‘s read()
method.
Here’s an example using the new INI file you just created:
>>> import configparser >>> config = configparser.ConfigParser() >>> config.read(r"C:\code\modified_mypy.ini") ['C:\\code\\modified_mypy.ini'] >>> config["mypy"] <Section: mypy> >>> config["mypy"]["warn_return_any"] 'True' >>> config["unknown"] Traceback (most recent call last): Python Shell, prompt 8, line 1 config["unknown"] File "c:\users\Mike\appdata\local\programs\python\python312\lib\configparser.py", line 941, in __getitem__ raise KeyError(key) builtins.KeyError: 'unknown'
You can access individual values using dictionary syntax. If you happen to try to access a section or an option that does not exist, you will receive a KeyError
.
The configparser
has a second reading method called read_string()
that you can use as well. Here is an example:
>>> sample_config = """ ... [mypy] ... warn_return_any = True ... warn_unused_configs = True ... ... # Per-module options: ... ... [mypy-mycode.foo.*] ... disallow_untyped_defs = True ... """>>> config = configparser.ConfigParser(allow_no_value=True) >>> config.read_string(sample_config) >>> config["mypy"]["warn_return_any"] 'True'
You use read_string()
to read in a multiline string and then access values inside of it. Pretty neat, eh?
You can also grab the section and them use list comprehensions to extract the options from each section:
>>> config.sections() ['mypy', 'mypy-mycode.foo.*'] >>> [option for option in config["mypy"]] ['warn_return_any', 'warn_unused_configs']
The code above is a handy example for getting at the configuration options quickly and easily.
Wrapping Up
Having a way to configure your application makes it more useful and allows the user more control over how their copy of the application works. In this article, you learned how about the following topics:
- An example INI file
- Creating a config file
- Editing a config file
- Reading a config file
The configparser library has more features than what is covered here. For example, you can use interpolation to preprocess values or customize the parser process. Check out the documentation for full details on those and other features.
In the meantime, have fun and enjoy this neat feature of Python!
Related Articles
You might also be interested in these related articles:
The post Python 101 – An Intro to Working with INI files Using configparser appeared first on Mouse Vs Python.