15

I have the following:

config = ConfigParser()
config.read('connections.cfg')
sections = config.sections()

How can I close the file opened with config.read?

In my case, as new sections/data are added to the config.cfg file, I update my wxtree widget. However, it only updates once, and I suspect it's because config.read leaves the file open.

And while we are at it, what is the main difference between ConfigParser and RawConfigParser?

Matthew Strawbridge
  • 19,940
  • 10
  • 72
  • 93
sqram
  • 7,069
  • 8
  • 48
  • 66
  • 1
    Come on, documentation is your friend: http://docs.python.org/library/configparser.html – Armandas Jun 13 '09 at 15:42
  • 8
    I did read it. Couldn't find how to close it. And as for ConfigParser vs RawConfigParser, the only difference I see is some methods. – sqram Jun 13 '09 at 15:51

4 Answers4

35

ConfigParser.read(filenames) actually takes care of that for you.

While coding I have encountered this issue and found myself asking myself the very same question:

Reading basically means I also have to close this resource after I'm done with it, right?

I read the answer you got here suggesting to open the file yourself and use config.readfp(fp) as an alternative. I looked at the documentation and saw that indeed there is no ConfigParser.close(). So I researched a little more and read the ConfigParser code implementation itself:

def read(self, filenames):
    """Read and parse a filename or a list of filenames.

    Files that cannot be opened are silently ignored; this is
    designed so that you can specify a list of potential
    configuration file locations (e.g. current directory, user's
    home directory, systemwide directory), and all existing
    configuration files in the list will be read.  A single
    filename may also be given.

    Return list of successfully read files.
    """
    if isinstance(filenames, basestring):
        filenames = [filenames]
    read_ok = []
    for filename in filenames:
        try:
            fp = open(filename)
        except IOError:
            continue
        self._read(fp, filename)
        fp.close()
        read_ok.append(filename)
    return read_ok

This is the actual read() method from ConfigParser.py source code. As you can see, 3rd line from the bottom, fp.close() closes the opened resource after its usage in any case. This is offered to you, already included in the box with ConfigParser.read() :)

user1555863
  • 2,567
  • 6
  • 35
  • 50
15

Use readfp instead of read:

with open('connections.cfg') as fp:
    config = ConfigParser()
    config.readfp(fp)
    sections = config.sections()
nobillygreen
  • 1,548
  • 5
  • 19
  • 27
Nicolas Dumazet
  • 7,147
  • 27
  • 36
  • 6
    [read_file](https://docs.python.org/3/library/configparser.html#configparser.ConfigParser.read_file) replaced readfp now – LukeDev Jul 25 '19 at 13:31
5

The difference between ConfigParser and RawConfigParser is that ConfigParser will attempt to "magically" expand references to other config variables, like so:

x = 9000 %(y)s
y = spoons

In this case, x will be 9000 spoons, and y will just be spoons. If you need this expansion feature, the docs recommend that you instead use SafeConfigParser. I don't know what exatly the difference between the two is. If you don't need the expansion (you probably don't) just need RawConfigParser.

Paul Fisher
  • 9,618
  • 5
  • 37
  • 53
4

To test your suspicion, use ConfigParser.readfp() and handle opening and closing of the file by yourself. Make the readfp call after the changes are made.

config = ConfigParser()
#...on each change
fp = open('connections.cfg')
config.readfp(fp)
fp.close()
sections = config.sections()
gimel
  • 83,368
  • 10
  • 76
  • 104
  • 1
    This doesn't work. `readfp` accepts a file object as argument, but your `read` accepts only a string with file path. Maybe you only forgot 2 characters in the code. – bluish Dec 30 '10 at 10:19
  • 1
    Thanks @bluish, a typo caught after 18 months is proof of relevance... The link and text were OK, now the code example is fixed. – gimel Dec 30 '10 at 12:44
  • 1
    D great! now you deservs an upvote. If you delete your comment I'll delete mine so the answer will be cleaner to read ;) – bluish Dec 30 '10 at 13:04