Intermediate
Putting parameters in configuration files can take some extra effort at the start, but then can save you a lot of time and heartache in the future. We are all tempted to simply hardcode parameters directly into our code as we save precious time when we write code, but then doing this properly can take extra effort. Some of us at least create constants or store parameters in a variable, while others store them in a class variable to keep this even cleaner. Arguably the best option is store these in a configuration file. In this article you’ll learn the steps compulsory to use configuration files in python 3. It will be strictly according to the official documentation of python 3.
ConfigParser is the class used to implement configuration files in python 3. The main function of using these files is to write python programs which can easily be modified by end users easily. The main aspect of this article is to know about the complete implementation of configuration files. We will cover the three main aspects in this article which are Setup, File format and Basic API.
Introduction to Python 3 Configuration Files
Configuration files can play a vital role in any program and its management. One of the popular approaches to separate code from configuration is to store these files in YAML, JSON or INI and not in .py format. One reason that .py files are not used is that Python 3 can be slower when it comes to reloading. You would need to restart the whole program if you stored your config in a python .py file. Also, the end user can modify the code at will if it is in .py format. Configuration files make it easier to modify or change the code. The data stored in configuration is to have separation so that the programmer can focus on code development and ensure that is clean as possible and the user only needs to touch the configuration file.
Setup of Python 3 ConfigParser
The class used to create configuration files is ConfigParser. This is a part of the standard python 3 library so no need to do any pip installation. We have to import it: “import configparser” to use it or there is another way of using it, it will work in both python2 and python 3, which is:
import configparser
File Format of configuration file
One convention that is used for the file format is to use the extension .ini (short for initial or initiation) but you can use the configuration based on your own or on clients preferences. There are different parts of configuration files.
- A configuration file consists of one or more sections.
- The section names are written in these delimiters [section name].
- The concept is similar to mapping. It consists of key-value pairs meaning there is a name of the configuration item (“key”) and the other the actual value of the configuration (“value”)
- Two operators are used to initialize or separate key-value pair assignment operator (=) or colon operator (:).
- You can even put in a comment using the # or ; prefix.
Example:
[default]
host = 192.168.1.1
port = 31
username = admin
password = admin
[database]
#database related configuration files
port = 22
forwardx11 = no
name = db_test
In the above configuration file example, we have two sections first is [default] and second is [database]. Each section has its own key-value pairs/entries like username = admin and name = db_test. So all of the key-value pairs belong to a given section, so it is easier to organise your configuration files. Finally the sentence with a prefix of # is for commenting
Reading the configuration file from python code
Now, we will talk about the method to read from the config file. As mentioned earlier, ConfigParser is the module/class used to create configuration files. First, ConfigParser object has to be initialized: config = configparser.ConfigParser(); The following are functions:
Initialization of ConfigParser
You can can initiate the configuration file with the following syntax. Here the variable “config” will contain all the values
config = configparser.ConfigParser()
Write to a Configuration file with ConfigParser
Although normally you normally edit to a configuration file in a text editor by hand, there are times where you want to programmatically write to a config file. For example, this could be to create a default config file which a user can then use as a basis to change or edit. You may also want to over-ride a config entry (after confirming with the user) that is erroneous.
Once the object is initialised, we can now write in it. There are ways through which we can initialize the section to write in the config file. We are going use the example mentioned above in file format. Let’s initialize the default section using dictionary.
Example:
config['default'] = {
"host" : "192.168.1.1",
"port" : "22",
"username" : "username",
"password" : "password"
}
Here, “default” is the name of the section (the part in the actual configuration file that had the square “[” and “]” brackets) and curly braces denote the start and end of a dictionary. Inside the dictionary are key-value pairs i.e. “host” is the key and “192.168.1.1” is the value separated by colon “:”
Now, let’s initialize the database section using empty dictionary and add the key-value pairs line by line.
Example:
config['database'] = {}
config['database']['port'] = "22"
config['database']['forwardx11'] = "no"
config['database']['name'] = "db_test"
Here, “database” is the name of the section and curly braces denote the same start and end of a dictionary. In this case, the dictionary is empty. Key-value pairs i.e. “port” is the key and “22” is the value separated by colon “=.” This method provides a lot more flexibility.
Here’s the full code so far:
import configparser
config = configparser.ConfigParser()
config['default'] = {
"host" : "192.168.1.1",
"port" : "22",
"username" : "username",
"password" : "password"
}
config['database'] = {}
config['database']['port'] = "22"
config['database']['forwardx11'] = "no"
config['database']['name'] = "db_test"
with open('test.ini', 'w') as configfile:
config.write(configfile);
After initializing the sections in config, you can now write it to a config file:
with open('test.ini', 'w') as configfile:
config.write(configfile);
Now, you will be able to see the file named test.ini created.
Read config from the config file using ConfigParser
The next step is to read the file which you just have created.
- The config file can be read by using read() method: config.read(‘test.ini’). This will read the test.ini file which you just created.
- If you want to print just the sections available in configuration file, method sections() can be used: config.sections().
- Next is getting the value of any key stored in the section. config[‘database’][‘name’]
This will give you the value which is “db_test” of the key called “name” stored in data_base section.
The following code will print out all the values stored against the keys in the default section using a for loop.
for key in config['default']:
print(config['default'][key])
Code:

Output:

Changing the datatype of the configuration value from ConfigParser
The datatype of the object of ConfigParser is string by default. This is fine for most situations, but then suppose you want to get a true/false value instead, or a number value to do maths operations. For this the string default may not work. We can typecast/covert the datatype of the object of configparser or the datatype of keys of section into any other type such as integer, float etc. In order to change the datatype of object, you have to covert it manually or by using getter methods. The best and the preferred way is to use getter methods.
There are three getter methods:
- getint();
- getfloat();
- getboolean();
Example: config['default'].getint('port')
getint() will covert the datatype of port key of section “default” into “integer”. If you use the typeof(); method on port then it will show integer type now.
There is another way of doing it:
Example: config.getboolean('data_base', 'forwardx11')
In this way, config file is invoking the getboolean() method and its takin two parameters as argument. The first is the name of the section and the other is the key whole value’s type will be changed.
What to do if a value is not available from a configfile
A fallback result can also be obtained. Fallback is the result obtained when the key or section we want to get isn’t available.
Example: config.get('default', 'database', fallback='not_database')
In this case, not_database will be returned if the “database” key isn’t available or the section default is not found.
Conclusion
We come to know about the setup i.e. importing the ConfigParser first to create configuration files. Next section was about the file format. There you can check about the basic syntax of creating a configuration file. It consists of sections and key-value pairs.
We played with the data types of keys in default and data_base sections. We can change datatypes using getter methods. Last but not the least, we studied about the basic api like write, read and about fallback.
Using configuration files is not difficult and can save a lot of time. So in your next coding work, take the extra few minutes to create a configuration file instead of hardcoding.
Full Code: ConfigParser Example Code
import configparser
config = configparser.ConfigParser()
#Set up default item for hosts using dictionary
config['default'] = {"host" : "192.168.1.1",
"port" : "22",
"username" : "username",
"password" : "password" }
#setup config item bytes
config['database'] = {}
config['database']['port'] = "22"
config['database']['forwardx11'] = "no"
config['database']['name'] = "db_test"
#Write default file
with open('test.ini', 'w') as configfile:
config.write(configfile)
#Open the file again to try to read it
config.read('test.ini')
#Print the sections
print(config.sections())
print( config['database']['name'] )
#Print each key pair
for key in config['default']:
print(config['default'][key])
#print the type of integer value
print (type (config['default'].getint('port')))
print( config.getboolean('database', 'forwardx11') )
#Print default value
print( config.get('default', 'databaseabc', fallback='not_database') )
Output:

Reference
https://docs.python.org/3/library/configparser.html
Want to see more useful tips?
Modern Python AI Stack: The Complete 2026 Tutorial Hub
The Python ecosystem in 2026 looks dramatically different from five years ago. AI tooling, faster data processing, async-first web frameworks, and a new generation of CLI builders have replaced what used to be the default stack. This hub page is your map to the modern Python toolkit — every link below points to a complete tutorial with code examples, common pitfalls, and FAQs.
The articles are grouped by what they help you build. Pick a starting point that matches your current project, or browse the categories if you’re just exploring what’s possible.
Python developer and educator with 15+ years building production systems across data engineering, web APIs, and AI tooling. Founder of Python How To Program — 270+ in-depth tutorials covering the modern Python stack.
View all tutorials by Pubs →Building with LLMs
Large language models stopped being a research curiosity and became a core dependency for production Python apps. These libraries make the integration story painless — structured outputs, multi-model routing, agent frameworks, and the new Model Context Protocol that’s standardizing how AI tools talk to each other.
Tutorials
- LangGraph for stateful AI agents — multi-step reasoning, tool use, state machines for production agent workflows
- MCP server for AI tool integration — the protocol that lets Claude, ChatGPT, and other AIs call your tools
- Pydantic AI for structured outputs — type-safe LLM responses validated at the API boundary
- LiteLLM for multi-model integration — one API, dozens of providers (OpenAI, Anthropic, local models)
- Instructor for structured LLM outputs — Pydantic-validated extraction from natural-language responses
- OpenAI API basics — chat completions, streaming, function calling, embeddings
- Ollama for local LLMs — run Llama, Mistral, and other open models on your own hardware
- Build a RAG system with LangChain — retrieval-augmented generation for grounded answers
Fast Data Processing
Pandas is the default, but the modern Python data stack has alternatives that handle bigger data faster. Polars (Rust-powered DataFrames), PyArrow (the columnar format that powers everything else), Dask (parallel pandas), and DuckDB (in-process analytical SQL) — each solves a specific scaling problem.
Tutorials
- Polars for fast DataFrames — 10-100x faster than pandas with a similar API
- PyArrow for columnar data — the storage and interchange format under Parquet and Arrow
- Dask for parallel + distributed computing — scale pandas, NumPy, and scikit-learn across cores or a cluster
- Parquet files with PyArrow — read/write the columnar file format used by every modern data warehouse
- Why Polars is faster — the architecture choices that make it 10-100x faster than pandas
Async Web APIs
FastAPI is the default for new Python APIs, but Litestar is gaining ground with cleaner DI and faster startup. Whichever you pick, the patterns are similar — type-hinted handlers, Pydantic validation, async by default, OpenAPI docs out of the box.
Tutorials
- Build a REST API with FastAPI — routes, Pydantic models, async endpoints, OpenAPI docs
- Litestar for async web APIs — the modern alternative to FastAPI with first-class dependency injection
- SQLModel for database models — Pydantic + SQLAlchemy in one declaration
- FastAPI authentication with OAuth2 + JWT — production-ready auth patterns
- FastAPI vs Flask — which framework wins for your use case
Modern CLI Tools
Typer turns Python functions into CLIs through type hints alone — no argument parsing, no boilerplate. It’s Click underneath but with the developer experience of FastAPI.
Tutorials
- Build a CLI with Typer — type-hint-driven CLI builder with auto-generated help
- Typer fundamentals — commands, options, arguments, subcommands, progress bars
Performance and Concurrency
asyncio is mature now, and TaskGroup (Python 3.11+) is the structured-concurrency primitive that replaces ad-hoc gather() patterns. For CPU-bound work, joblib parallelizes across cores with caching built in.
Tutorials
- Joblib for parallel computing + caching — the cleanest parallelism API in the Python stdlib ecosystem
- asyncio TaskGroup tutorial — structured concurrency replaces gather()
Modern Dev Tools
The Python developer experience improved a lot in 2024-2026. watchfiles replaces watchdog as the standard for file-change detection (Rust-powered, async-friendly). uv is the new pip+venv replacement. These small upgrades compound.
Tutorials
- watchfiles for file monitoring — the modern Rust-powered replacement for watchdog
- uv package manager — pip + venv + pyenv in a single Rust binary
How to use this hub
Three suggested paths:
- Building an LLM-powered feature? Start with Instructor for structured outputs, then graduate to LangGraph when you need multi-step reasoning.
- Modernizing a data pipeline? Read the Polars overview, then dive into the migration guide from pandas.
- Building a new web API? FastAPI for proven, Litestar for newer-with-cleaner-DI.
Bookmark this page — every time we publish a new article in the modern Python stack, it gets added here.
Continue Learning Python
Tutorials you might also find useful:
- How To Use Python Pydantic AI for Structured AI Outputs
- How To Build an AI Agent with LangGraph in Python
- How To Use Python Textual for Modern Terminal UIs
- How To Use Python Loguru for Modern Application Logging
- How To Use Python httpx for Modern HTTP Requests
- How To Use Python MCP Server for AI Tool Integration
Frequently Asked Questions
What is ConfigParser used for in Python?
ConfigParser is a built-in Python module for reading and writing configuration files in INI format. It handles settings organized into sections with key-value pairs, making it easy to store and retrieve application configuration without hardcoding values.
What format does ConfigParser use?
ConfigParser uses the INI file format with sections in square brackets ([section]), followed by key-value pairs using = or : as delimiters. Comments start with # or ;. There is always a [DEFAULT] section for fallback values.
How do I read a config file with ConfigParser?
Create a ConfigParser() instance, call config.read('filename.ini'), then access values with config['section']['key'] or config.get('section', 'key'). Use getint(), getfloat(), or getboolean() for type conversion.
Can ConfigParser handle nested sections?
No, ConfigParser does not support nested sections natively. For nested configuration structures, consider using TOML (tomllib in Python 3.11+), YAML (PyYAML), or JSON configuration files instead.
What is the difference between ConfigParser and JSON for configuration?
ConfigParser uses human-friendly INI format with sections and is ideal for simple settings. JSON supports nested structures and lists but lacks comments. ConfigParser has built-in type conversion methods and a DEFAULT section for fallback values, while JSON requires manual type handling.
Related Articles
- How To Use TOML for Configuration Files
- Managing Environment Variables with dotenv
- How To Use Pathlib for File Paths
Continue Learning Python
Tutorials you might also find useful:
- How To Use Python TOML For Configuration Files Instead of INI
- How To Use Python dynaconf for Configuration Management
- How To Work with ZIP Files in Python
- How To Use Python tempfile for Temporary Files and Directories
- How To Read and Write CSV Files in Python
- How To Read and Write JSON Files in Python
Trackbacks/Pingbacks