Using ConfigParser to read a file without section name
Alex Martelli provided a solution for using ConfigParser
to parse .properties
files (which are apparently section-less config files).
His solution is a file-like wrapper that will automagically insert a dummy section heading to satisfy ConfigParser
's requirements.
How to use python's configparser to write a file without sections
Stumbled on a less ugly way of doing this:
text = '\n'.join(['='.join(item) for item in parser.items('top')])
with open('foo.conf', 'w') as config_file:
config_file.write(text)
Is there a way to read/write config files without section headers in python?
Seems like a very simple config file syntax. Why not just write your own config parser?
conf = {}
with open('config.cfg') as fp:
for line in fp:
if line.startswith('#'):
continue
key, val = line.strip().split('=')
conf[key] = val
Configparser set with no section
You could use the csv
module to do most of work of parsing the file and writing it back out after you made changes -- so it should be relatively easy to use. I got the idea from one of the answers to a similar question titled Using ConfigParser to read a file without section name.
However I've made a number of changes to it, including coding it to work in both Python 2 & 3, unhardcoding the key/value delimiter it uses so it could be almost anything (but be a colon by default), along with several optimizations.
from __future__ import print_function # For main() test function.
import csv
import sys
PY3 = sys.version_info.major > 2
def read_properties(filename, delimiter=':'):
""" Reads a given properties file with each line in the format:
key<delimiter>value. The default delimiter is ':'.
Returns a dictionary containing the pairs.
filename -- the name of the file to be read
"""
open_kwargs = dict(mode='r', newline='') if PY3 else dict(mode='rb')
with open(filename, **open_kwargs) as csvfile:
reader = csv.reader(csvfile, delimiter=delimiter, escapechar='\\',
quoting=csv.QUOTE_NONE)
return {row[0]: row[1] for row in reader}
def write_properties(filename, dictionary, delimiter=':'):
""" Writes the provided dictionary in key-sorted order to a properties
file with each line of the format: key<delimiter>value
The default delimiter is ':'.
filename -- the name of the file to be written
dictionary -- a dictionary containing the key/value pairs.
"""
open_kwargs = dict(mode='w', newline='') if PY3 else dict(mode='wb')
with open(filename, **open_kwargs) as csvfile:
writer = csv.writer(csvfile, delimiter=delimiter, escapechar='\\',
quoting=csv.QUOTE_NONE)
writer.writerows(sorted(dictionary.items()))
def main():
data = {
'Answer': '6*7 = 42',
'Knights': 'Ni!',
'Spam': 'Eggs',
}
filename = 'test.properties'
write_properties(filename, data) # Create csv from data dictionary.
newdata = read_properties(filename) # Read it back into a new dictionary.
print('Properties read: ')
print(newdata)
print()
# Show the actual contents of file.
with open(filename, 'rb') as propfile:
contents = propfile.read().decode()
print('File contains: (%d bytes)' % len(contents))
print('contents:', repr(contents))
print()
# Tests whether data is being preserved.
print(['Failure!', 'Success!'][data == newdata])
if __name__ == '__main__':
main()
Python ConfigParser.NoSectionError: No section:
You're defining your path with backslashes:
configFilePath = 'E:\Python\configfile\test.txt'
These get interpreted as escapes, and as a result the correct file isn't being loaded. (Unfortunately, the error message doesn't help much in this instance.) You either need to escape them, or use a raw string:configFilePath = r'E:\Python\configfile\test.txt'
configparser does not show sections
From the docs, config.read()
takes in a filename (or list of them), not a file descriptor object:
A file object is an iterable of strings, so basically the config parser is trying to read each string in the file as a filename. Which is sort of interesting and silly, because if you passed it a file that contained the filename of your actual config...it would work.
read
(
filenames, encoding=None
)
Attempt to read and parse an iterable of filenames, returning a list of filenames which were successfully parsed.
If filenames is a string, a bytes object or a path-like object, it is treated as a single filename. ...
If none of the named files exist, the ConfigParser instance will contain an empty dataset. ...
Anyways, you should pass the filename directly to config.read()
, i.e.
config.read("ini/inifile.ini")
Or, if you want to use a file descriptor object instead, simply use config.read_file(f)
. Read the docs for read_file()
for more information.
As an aside, you are duplicating some of the work the context manager is doing for no gain. You can use the
with
block without creating the object explicitly first or closing it after (it will get closed automatically). Keep it simple:with open("path/to/file.txt") as f:
do_stuff_with_file(f)
How to write ini-files without sections?
[NB: the following is written for Python 3; you would need to make a couple of minor changes to make it run under Python 2.]
Maybe something like this; here, I write to an io.StringIO
object in memory, then take everything but the first line and write that out to the target file.
import configparser
import io
buf = io.StringIO()
ini_writer = configparser.ConfigParser()
ini_writer.set('DEFAULT', 'option1', '99')
ini_writer.set('DEFAULT', 'option2', '34')
ini_writer.set('DEFAULT', 'do_it', 'True')
ini_writer.write(buf)
buf.seek(0)
next(buf)
with open('my.ini', 'w') as fd:
fd.write(buf.read())
By using the section name DEFAULT
we avoid having to create a new section first.This results in:
$ cat my.ini
option1 = 99
option2 = 34
do_it = True
DEFAULT section with no values in config text file
DEFAULT
is a “special” section that is always present in a ConfigParser
instance. It stores fallback values that are used as defaults when a value in another section is missing.
If you want to iterate over the sections in your configuration and want to exclude the default, use sections()
:
>>> for key in config.sections():
... print(key)
1
2
3
4
5
Related Topics
Is There a Numpy Builtin to Reject Outliers from a List
When Should an Attribute Be Private and Made a Read-Only Property
Convert Date to Datetime in Python
Continuing in Python's Unittest When an Assertion Fails
What Does 'Wb' Mean in This Code, Using Python
Why Is the Apt-Get Function Not Working in the Terminal on MAC Os X V10.9 (Mavericks)
Conditional with Statement in Python
Django - Makemigrations - No Changes Detected
First Python List Index Greater Than X
In Python, What Happens When You Import Inside of a Function
How to Save and Restore Multiple Variables in Python
Pandas Dataframe Aggregate Function Using Multiple Columns