Domanda

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.

È stato utile?

Soluzione

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()

Altri suggerimenti

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.

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top