4

Is there a way for configparser in python to set a value without having sections in the config file?

If not please tell me of any alternatives.

Thank you.

more info: So basically I have a config file with format: Name: value It's a system file that I want to change the value for a given name. I was wondering if this can be done easily with a module instead of manually writing a parser.

Cobra Kai Dojo
  • 1,018
  • 2
  • 12
  • 25
  • ConfigParser is primarily intended to be used for _reading_ settings from files, but it sounds like you want to add or change the contents of one, correct? That's a harder problem than just getting it to read a file that doesn't have any sections... – martineau Jul 22 '13 at 15:35

3 Answers3

3

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()
martineau
  • 119,623
  • 25
  • 170
  • 301
  • 2
    Changing `PY3=sys.version_info[0] > 2` makes it compliant with Python 2.6.6, Python 3.4.1 and Jython 2.7b2. In that version of Jython `sys.version_info` returns a tuple. Thanks for your code. – Jorge Lavín Sep 01 '14 at 09:11
  • @martineau: This solution is really helpful. I can read data i can write and append. It would be really helpful if you can provide solution to edit the config file. Eg scenario is, suppose i have added some users to sshd_config file by appending each time using your method. Now i want to remove a user and its corresponding settings then what approach i should use. Please help. Also please let me know if you did not get my question. Thank you. – Abhishek Verma Sep 14 '19 at 12:25
  • @AbhishekVerma: The functions in this answer are passed and return data in dictionary format, so it seems like you ought to be able to do what you want using them by modifying that dictionary — although I'm not familiar with the sshd_config file format. Anyway, if you can't figure out how to do that, I suggest you post a new question. – martineau Sep 14 '19 at 14:57
0

I know of no way to do that with configparser, which is very section-oriented.

An alternative would be to use the Voidspace Python module named ConfigObj by Michael Foord. In the The Advantages of ConfigObj section of an article he wrote titled An Introduction to ConfigObj, it says:

The biggest advantage of ConfigObj is simplicity. Even for trivial configuration files, where you just need a few key value pairs, ConfigParser requires them to be inside a 'section'. ConfigObj doesn't have this restriction, and having read a config file into memory, accessing members is trivially easy.

Emphasis mine.

martineau
  • 119,623
  • 25
  • 170
  • 301
-1

Personally I like to do my config files as XML. An example (taken from the ConfigObj article for comparison purposes) you could create a file called config.xml with the following contents:

<?xml version="1.0"?>
<config>
  <name>Michael Foord</name>
  <dob>12th August 1974</dob>
  <nationality>English</nationality>
</config>

In Python, you could then get the values doing something like this:

>>> import xml.etree.cElementTree as etree
>>> config = etree.parse("config.xml")
>>> config.find("name").text
'Michael Foord'
>>> config.find("name").text = "Jim Beam"
>>> config.write("config.xml")

Now if we look at config.xml we see:

<config>
  <name>Jim Beam</name>
  <dob>12th August 1974</dob>
  <nationality>English</nationality>
</config>

The benefits are the same as that of general XML - it's human readable, there are a number of decent parsers that already exist in pretty much every programming language you can imagine, and it supports grouping and attributes. As an added bonus when your config files get larger you can also incorporate XML validation (using schemas) to find mistakes before runtime.

  • Actually I don't have the ability of doing this. I already have a .conf file with the values in a format like "name: value" and I try to modify them. – Cobra Kai Dojo Jul 22 '13 at 12:03
  • @Haros: What are you using to read the .config file you already have? – martineau Jul 22 '13 at 15:00
  • 1
    @Haros Any constraints on additional approaches should be added to the question. –  Jul 22 '13 at 17:35