Using ConfigParser to read a file without section name

前端 未结 7 2084
星月不相逢
星月不相逢 2020-11-27 03:36

I am using ConfigParser to read the runtime configuration of a script.

I would like to have the flexibility of not providing a section name (there are s

相关标签:
7条回答
  • 2020-11-27 03:41

    Blueicefield's answer mentioned configobj, but the original lib only supports Python 2. It now has a Python 3+ compatible port:

    https://github.com/DiffSK/configobj

    APIs haven't changed, see it's doc.

    0 讨论(0)
  • 2020-11-27 03:51

    You can use the ConfigObj library to do that simply : http://www.voidspace.org.uk/python/configobj.html

    Updated: Find latest code here.

    If you are under Debian/Ubuntu, you can install this module using your package manager :

    apt-get install python-configobj
    

    An example of use:

    from configobj import ConfigObj
    
    config = ConfigObj('myConfigFile.ini')
    config.get('key1') # You will get val1
    config.get('key2') # You will get val2
    
    0 讨论(0)
  • 2020-11-27 03:55

    You can do this in a single line of code.

    In python 3, prepend a fake section header to your config file data, and pass it to read_string().

    from configparser import ConfigParser
    
    parser = ConfigParser()
    with open("foo.conf") as stream:
        parser.read_string("[top]\n" + stream.read())  # This line does the trick.
    

    You could also use itertools.chain() to simulate a section header for read_file(). This might be more memory-efficient than the above approach, which might be helpful if you have large config files in a constrained runtime environment.

    from configparser import ConfigParser
    from itertools import chain
    
    parser = ConfigParser()
    with open("foo.conf") as lines:
        lines = chain(("[top]",), lines)  # This line does the trick.
        parser.read_file(lines)
    

    In python 2, prepend a fake section header to your config file data, wrap the result in a StringIO object, and pass it to readfp().

    from ConfigParser import ConfigParser
    from StringIO import StringIO
    
    parser = ConfigParser()
    with open("foo.conf") as stream:
        stream = StringIO("[top]\n" + stream.read())  # This line does the trick.
        parser.readfp(stream)
    

    With any of these approaches, your config settings will be available in parser.items('top').

    You could use StringIO in python 3 as well, perhaps for compatibility with both old and new python interpreters, but note that it now lives in the io package and readfp() is now deprecated.

    Alternatively, you might consider using a TOML parser instead of ConfigParser.

    0 讨论(0)
  • 2020-11-27 03:58

    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.

    0 讨论(0)
  • 2020-11-27 03:59

    The easiest way to do this is to use python's CSV parser, in my opinion. Here's a read/write function demonstrating this approach as well as a test driver. This should work provided the values are not allowed to be multi-line. :)

    import csv
    import operator
    
    def read_properties(filename):
        """ Reads a given properties file with each line of the format key=value.  Returns a dictionary containing the pairs.
    
        Keyword arguments:
            filename -- the name of the file to be read
        """
        result={ }
        with open(filename, "rb") as csvfile:
            reader = csv.reader(csvfile, delimiter='=', escapechar='\\', quoting=csv.QUOTE_NONE)
            for row in reader:
                if len(row) != 2:
                    raise csv.Error("Too many fields on row with contents: "+str(row))
                result[row[0]] = row[1] 
        return result
    
    def write_properties(filename,dictionary):
        """ Writes the provided dictionary in key-sorted order to a properties file with each line of the format key=value
    
        Keyword arguments:
            filename -- the name of the file to be written
            dictionary -- a dictionary containing the key/value pairs.
        """
        with open(filename, "wb") as csvfile:
            writer = csv.writer(csvfile, delimiter='=', escapechar='\\', quoting=csv.QUOTE_NONE)
            for key, value in sorted(dictionary.items(), key=operator.itemgetter(0)):
                    writer.writerow([ key, value])
    
    def main():
        data={
            "Hello": "5+5=10",
            "World": "Snausage",
            "Awesome": "Possum"
        }
    
        filename="test.properties"
        write_properties(filename,data)
        newdata=read_properties(filename)
    
        print "Read in: "
        print newdata
        print
    
        contents=""
        with open(filename, 'rb') as propfile:
            contents=propfile.read()
        print "File contents:"
        print contents
    
        print ["Failure!", "Success!"][data == newdata]
        return
    
    if __name__ == '__main__': 
         main() 
    
    0 讨论(0)
  • 2020-11-27 04:03

    Having ran into this problem myself, I wrote a complete wrapper to ConfigParser (the version in Python 2) that can read and write files without sections transparently, based on Alex Martelli's approach linked on the accepted answer. It should be a drop-in replacement to any usage of ConfigParser. Posting it in case anyone in need of that finds this page.

    import ConfigParser
    import StringIO
    
    class SectionlessConfigParser(ConfigParser.RawConfigParser):
        """
        Extends ConfigParser to allow files without sections.
    
        This is done by wrapping read files and prepending them with a placeholder
        section, which defaults to '__config__'
        """
    
        def __init__(self, *args, **kwargs):
            default_section = kwargs.pop('default_section', None)
            ConfigParser.RawConfigParser.__init__(self, *args, **kwargs)
    
            self._default_section = None
            self.set_default_section(default_section or '__config__')
    
        def get_default_section(self):
            return self._default_section
    
        def set_default_section(self, section):
            self.add_section(section)
    
            # move all values from the previous default section to the new one
            try:
                default_section_items = self.items(self._default_section)
                self.remove_section(self._default_section)
            except ConfigParser.NoSectionError:
                pass
            else:
                for (key, value) in default_section_items:
                    self.set(section, key, value)
    
            self._default_section = section
    
        def read(self, filenames):
            if isinstance(filenames, basestring):
                filenames = [filenames]
    
            read_ok = []
            for filename in filenames:
                try:
                    with open(filename) as fp:
                        self.readfp(fp)
                except IOError:
                    continue
                else:
                    read_ok.append(filename)
    
            return read_ok
    
        def readfp(self, fp, *args, **kwargs):
            stream = StringIO()
    
            try:
                stream.name = fp.name
            except AttributeError:
                pass
    
            stream.write('[' + self._default_section + ']\n')
            stream.write(fp.read())
            stream.seek(0, 0)
    
            return ConfigParser.RawConfigParser.readfp(self, stream, *args,
                                                       **kwargs)
    
        def write(self, fp):
            # Write the items from the default section manually and then remove them
            # from the data. They'll be re-added later.
            try:
                default_section_items = self.items(self._default_section)
                self.remove_section(self._default_section)
    
                for (key, value) in default_section_items:
                    fp.write("{0} = {1}\n".format(key, value))
    
                fp.write("\n")
            except ConfigParser.NoSectionError:
                pass
    
            ConfigParser.RawConfigParser.write(self, fp)
    
            self.add_section(self._default_section)
            for (key, value) in default_section_items:
                self.set(self._default_section, key, value)
    
    0 讨论(0)
提交回复
热议问题