Created
May 21, 2020 00:20
-
-
Save Jckf/175236b8b68bd9a6684130ae5ec0c28d to your computer and use it in GitHub Desktop.
Reading and writing INI files in Python (for Luke Saward)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Crude ini file reader/writer. Tries to retain original file formatting when writing. | |
# Author: Jim C K Flaten <[email protected]> | |
import os | |
import json | |
def parse_ini(filename, updates = {}): | |
# Prepare some variables we need. | |
ini = {} | |
section = None | |
# Open this file(s). | |
r = open(filename, "r") | |
w = open(filename + ".tmp", "w") if updates else None | |
# Loop over each line. | |
for raw_line in r.readlines(): | |
# Remove leading and trailing whitespace/special characters. | |
line = raw_line.strip(); | |
# Empty line or comment. | |
if not line or line[-1] == "#": | |
if w: w.write(raw_line) | |
continue | |
# Section header. | |
if line[:1] == "[" and line[-1] == "]": | |
# We have left-over updates for the current section (new keys). Write them before entering a new section. | |
if section and section in updates: | |
for key in updates[section]: | |
w.write(key + "=" + str(updates[section][key]) + "\n") | |
# End the section with an empty line for readability. | |
w.write("\n") | |
del updates[section] | |
# Section name without the brackets. | |
section = line[1:-1] | |
# Initialize an empty dictionary to store this section in. | |
if not section in ini.keys(): | |
ini[section] = {} | |
# Copy the line "as is" if we're writing. | |
if w: w.write(raw_line) | |
continue | |
# We've found something that's not inside a section? Skip it. | |
if not section: | |
# Copy the line "as is" if we're writing. | |
if w: w.write(raw_line) | |
continue | |
# Split into key and value pair. | |
pair = line.split("=") | |
# Clean up the values in case there was whitespace around the equals character. | |
key = pair[0].rstrip() | |
value = pair[1].lstrip() | |
# Do we have an update for this? | |
if section in updates.keys() and key in updates[section].keys(): | |
# Pop value from the updates dict to signify that we've completed it. | |
value = updates[section].pop(key) | |
# If we're writing and the value isn't None (to be deleted), write the new value. | |
if w and value != None: w.write(key + "=" + str(value) + "\n") | |
# No more updates left in this section. | |
if not updates[section]: | |
del updates[section] | |
elif w: | |
# No update, but we're writing. Copy the line "as is". | |
w.write(raw_line) | |
# Store it for return, unless it was unset. | |
if value != None: | |
ini[section][key] = value | |
# Close the read handle. | |
r.close() | |
# Close the write handle if we have one, and replace the file with our new one. | |
if w: | |
w.close() | |
os.replace(filename + ".tmp", filename) | |
return ini | |
##################### | |
# EXAMPLE USE BELOW # | |
##################### | |
# Load the current ini file. | |
config = parse_ini("config.ini") | |
# Fetch some values from the dict to look at. | |
authors = set(map(str.strip, config["General"]["authors"].split(","))) | |
rerecord_count = int(config["General"]["rerecord_count"]) | |
flipflop = "flipflop" in config["General"]; | |
print("Current authors are: " + ", ".join(authors)) | |
print("Current rerecord count is: " + str(rerecord_count)) | |
print("Current flip-flop state: " + str(flipflop)) | |
print() | |
# Modify some of the data. | |
authors.add("Jim") # "Jim" will always be added to authors list, but never duplicated. | |
rerecord_count += 1 # Rerecord count will increment by 1 every execution. | |
flipflop = None if flipflop else True # Flip-flop will switch back and forth between not existing, and being True. | |
print("New authors are: " + ", ".join(authors)) | |
print("New rerecord count is: " + str(rerecord_count)) | |
print("New flip-flop state: " + str(flipflop)) | |
# Create an update dict. | |
updates = {} | |
updates["General"] = {} | |
updates["General"]["authors"] = ", ".join(authors) | |
updates["General"]["rerecord_count"] = rerecord_count | |
updates["General"]["flipflop"] = flipflop | |
# Write the updates to file. | |
parse_ini("config.ini", updates) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment