Python subclassing ConfigParser I've never done anything like this before so I'd like someone else to look at this before I get too carried away :)

Am I making this more complicated than it needs to be?  I'm trying to make it EASY for other modules/scripts on this system to store and retrieve their settings. Hence why I trap the ConfigParser.NoOptionError error and return None and create the section if it doesn't exist in the set() method.

Suggestions?

import ConfigParser
import os

from ast import literal_eval as Eval

class _ConfParse(ConfigParser.ConfigParser):
    def __init__(self, confpath, conffile):
        ConfigParser.ConfigParser.__init__(self)
        self.conf_file = os.path.join(confpath, conffile)
        try: self.readfp(open(self.conf_file), 'r')
        except IOError as Err:
            if Err.errno == 2: pass
            else: raise Err

    def set(self, section, option, value):
        if self.has_section(section):
            ConfigParser.ConfigParser.set(self, section, option, str(value))
        else:
            self.add_section(section)
            ConfigParser.ConfigParser.set(self, section, option, str(value))

    def get(self, section, option):
        try: return Eval(ConfigParser.ConfigParser.get(self, section, option))
        except ConfigParser.NoOptionError: return None

    def save(self):
        self.write(open(self.conf_file, 'w'))

    def __del__(self):
        self.save()

class LocalConfig(_ConfParse):
    def __init__(self, conffile, confpath = '/etc/local/cnf'):
        _ConfParse.__init__(self, confpath, conffile)

class SysConfig(_ConfParse):
    def __init__(self, conffile, confpath = '/etc/sys/cnf'):
        _ConfParse.__init__(self, confpath, conffile)
One problem I see is that returning None from your modified get() method conflicts with the normal case of a valueless option (from the bottom of the module docs for ConfigParser):

&gt;&gt;&gt; import ConfigParser
&gt;&gt;&gt; import io

&gt;&gt;&gt; sample_config = """
... [mysqld]
... user = mysql
... pid-file = /var/run/mysqld/mysqld.pid
... skip-external-locking
... old_passwords = 1
... skip-bdb
... skip-innodb
... """
&gt;&gt;&gt; config = ConfigParser.RawConfigParser(allow_no_value=True)
&gt;&gt;&gt; config.readfp(io.BytesIO(sample_config))

&gt;&gt;&gt; # Settings with values are treated as before:
&gt;&gt;&gt; config.get("mysqld", "user")
'mysql'

&gt;&gt;&gt; # Settings without values provide None:
&gt;&gt;&gt; config.get("mysqld", "skip-bdb")

&gt;&gt;&gt; # Settings which aren't specified still raise an error:
&gt;&gt;&gt; config.get("mysqld", "does-not-exist")
Traceback (most recent call last):
  ...
ConfigParser.NoOptionError: No option 'does-not-exist' in section: 'mysqld'


Note the second-to-last example commented as "Settings without values provide None:"  Of course this isn't an issue if you intend to exclude this sort of option.  Other than that, I like the auto-section feature.

Though, I'd lean towards adding to the interface rather than masking and changing the behavior, so instead of replacing get/set, add safe_ versions:

def safe_set(self, section, option, value):
    if self.has_section(section):
        self.set(section, option, str(value))
    else:
        self.add_section(section)
        self.set(section, option, str(value))

def safe_get(self, section, option):
    if self.has_option(section, option):
        return self.get(section, option)
    else:
        return None


This would make it more flexible as code would still have access to ConfigParser's normal interface and the option of using the "safe" calls which don't throw exceptions.