I need to read, write and create an INI file with Python3.
FILE.INI
default_path = "/path/name/" default_file = "file.txt"
Python File:
# Read file and and create if it not exists config = iniFile( 'FILE.INI' ) # Get "default_path" config.default_path # Print (string)/path/name print config.default_path # Create or Update config.append( 'default_path', 'var/shared/' ) config.append( 'default_message', 'Hey! help me!!' )
UPDATED FILE.INI
default_path = "var/shared/" default_file = "file.txt" default_message = "Hey! help me!!"
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
This can be something to start with:
import configparser
config = configparser.ConfigParser()
config.read('FILE.INI')
print(config['DEFAULT']['path']) # -> "/path/name/"
config['DEFAULT']['path'] = '/var/shared/' # update
config['DEFAULT']['default_message'] = 'Hey! help me!!' # create
with open('FILE.INI', 'w') as configfile: # save
config.write(configfile)
You can find more at the official configparser documentation.
Method 2
Here’s a complete read, update and write example.
Input file, test.ini
[section_a] string_val = hello bool_val = false int_val = 11 pi_val = 3.14
Working code.
try:
from configparser import ConfigParser
except ImportError:
from ConfigParser import ConfigParser # ver. < 3.0
# instantiate
config = ConfigParser()
# parse existing file
config.read('test.ini')
# read values from a section
string_val = config.get('section_a', 'string_val')
bool_val = config.getboolean('section_a', 'bool_val')
int_val = config.getint('section_a', 'int_val')
float_val = config.getfloat('section_a', 'pi_val')
# update existing value
config.set('section_a', 'string_val', 'world')
# add a new section and some values
config.add_section('section_b')
config.set('section_b', 'meal_val', 'spam')
config.set('section_b', 'not_found_val', '404')
# save to a file
with open('test_update.ini', 'w') as configfile:
config.write(configfile)
Output file, test_update.ini
[section_a] string_val = world bool_val = false int_val = 11 pi_val = 3.14 [section_b] meal_val = spam not_found_val = 404
The original input file remains untouched.
Method 3
http://docs.python.org/library/configparser.html
Python’s standard library might be helpful in this case.
Method 4
The standard ConfigParser normally requires access via config['section_name']['key'], which is no fun. A little modification can deliver attribute access:
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
AttrDict is a class derived from dict which allows access via both dictionary keys and attribute access: that means a.x is a['x']
We can use this class in ConfigParser:
config = configparser.ConfigParser(dict_type=AttrDict)
config.read('application.ini')
and now we get application.ini with:
[general] key = value
as
>>> config._sections.general.key 'value'
Method 5
ConfigObj is a good alternative to ConfigParser which offers a lot more flexibility:
- Nested sections (subsections), to any level
- List values
- Multiple line values
- String interpolation (substitution)
- Integrated with a powerful validation system including automatic type checking/conversion repeated sections and allowing default values
- When writing out config files, ConfigObj preserves all comments and the order of members and sections
- Many useful methods and options for working with configuration files (like the ‘reload’ method)
- Full Unicode support
It has some draw backs:
- You cannot set the delimiter, it has to be
=… (pull request) - You cannot have empty values, well you can but they look liked:
fuabr =instead of justfubarwhich looks weird and wrong.
Method 6
contents in my backup_settings.ini file
[Settings] year = 2020
python code for reading
import configparser
config = configparser.ConfigParser()
config.read('backup_settings.ini') #path of your .ini file
year = config.get("Settings","year")
print(year)
for writing or updating
from pathlib import Path
import configparser
myfile = Path('backup_settings.ini') #Path of your .ini file
config.read(myfile)
config.set('Settings', 'year','2050') #Updating existing entry
config.set('Settings', 'day','sunday') #Writing new entry
config.write(myfile.open("w"))
output
[Settings] year = 2050 day = sunday
Method 7
There are some problems I found when used configparser such as – I got an error when I tryed to get value from param:
destination=my-serverbackup$%USERNAME%
It was because parser can’t get this value with special character ‘%’. And then I wrote a parser for reading ini files based on ‘re’ module:
import re
# read from ini file.
def ini_read(ini_file, key):
value = None
with open(ini_file, 'r') as f:
for line in f:
match = re.match(r'^ *' + key + ' *= *.*$', line, re.M | re.I)
if match:
value = match.group()
value = re.sub(r'^ *' + key + ' *= *', '', value)
break
return value
# read value for a key 'destination' from 'c:/myconfig.ini'
my_value_1 = ini_read('c:/myconfig.ini', 'destination')
# read value for a key 'create_destination_folder' from 'c:/myconfig.ini'
my_value_2 = ini_read('c:/myconfig.ini', 'create_destination_folder')
# write to an ini file.
def ini_write(ini_file, key, value, add_new=False):
line_number = 0
match_found = False
with open(ini_file, 'r') as f:
lines = f.read().splitlines()
for line in lines:
if re.match(r'^ *' + key + ' *= *.*$', line, re.M | re.I):
match_found = True
break
line_number += 1
if match_found:
lines[line_number] = key + ' = ' + value
with open(ini_file, 'w') as f:
for line in lines:
f.write(line + 'n')
return True
elif add_new:
with open(ini_file, 'a') as f:
f.write(key + ' = ' + value)
return True
return False
# change a value for a key 'destination'.
ini_write('my_config.ini', 'destination', '//server/backups$/%USERNAME%')
# change a value for a key 'create_destination_folder'
ini_write('my_config.ini', 'create_destination_folder', 'True')
# to add a new key, we need to use 'add_new=True' option.
ini_write('my_config.ini', 'extra_new_param', 'True', True)
Method 8
You could use python-benedict, it’s a dict subclass that provides normalized I/O support for most common formats, including ini.
from benedict import benedict
# path can be a ini string, a filepath or a remote url
path = 'path/to/config.ini'
d = benedict.from_ini(path)
# do stuff with your dict
# ...
# write it back to disk
d.to_ini(filepath=path)
It’s well tested and documented, check the README to see all the features:
Documentation: https://github.com/fabiocaccamo/python-benedict
Installation: pip install python-benedict
Note: I am the author of this project
Method 9
Use nested dictionaries. Take a look:
INI File: example.ini
[Section] Key = Value
Code:
class IniOpen:
def __init__(self, file):
self.parse = {}
self.file = file
self.open = open(file, "r")
self.f_read = self.open.read()
split_content = self.f_read.split("n")
section = ""
pairs = ""
for i in range(len(split_content)):
if split_content[i].find("[") != -1:
section = split_content[i]
section = string_between(section, "[", "]") # define your own function
self.parse.update({section: {}})
elif split_content[i].find("[") == -1 and split_content[i].find("="):
pairs = split_content[i]
split_pairs = pairs.split("=")
key = split_pairs[0].trim()
value = split_pairs[1].trim()
self.parse[section].update({key: value})
def read(self, section, key):
try:
return self.parse[section][key]
except KeyError:
return "Sepcified Key Not Found!"
def write(self, section, key, value):
if self.parse.get(section) is None:
self.parse.update({section: {}})
elif self.parse.get(section) is not None:
if self.parse[section].get(key) is None:
self.parse[section].update({key: value})
elif self.parse[section].get(key) is not None:
return "Content Already Exists"
Apply code like so:
ini_file = IniOpen("example.ini")
print(ini_file.parse) # prints the entire nested dictionary
print(ini_file.read("Section", "Key") # >> Returns Value
ini_file.write("NewSection", "NewKey", "New Value"
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0