Trabajando con ficheros de configuración en Python: ConfigParser mejorado

Python
Etiquetas:

Cómo pudisteis leer en mi anterior entrada sobre Python y ConfigParser, a pesar de su efectividad, algunas cosas de esta librería no son precísamente “directas”. Así que … estuve investigando si alguien tenía alguna clase mejorada de ConfigParser.

En la primera búsqueda realizada encontré esta entrada (http://www.decalage.info/en/python/configparser), y encontré una clase mejorada para lectura (no para escritura) entre los comentarios.

Rebuscando más, encontré un proyecto en Python con una clase mejorada muy potente, aunque altamente personalizada para dicho proyecto: , e incapaz de usar nada, fundamentalmente porque es específica para ese proyecto.

La mejor opción la he encontrado en GitHub: https://github.com/songqiang/configparser/blob/master/ConfigParser.py, aunque es sólo de lectura, y no trabaja la escritura.

Así que, no tengo más remedio que crearme mi propio ConfigParser, que lo he subido a GitHub.

""" ConfigParserAdvanced,
developer by David Trillo Montero
write me at manejandodatos@gmail.com

Visit my website: http://www.manejandodatos.es """
# Versión 0.7.0 - 20140110

import ConfigParser

class ConfigParserAdvanced():
    def __init__(self, sfile, main_section = None, getdefault = ''):
        self.file = sfile
        self.reload()
        self.main_section = main_section
        self.getdefault = getdefault

    def reload(self):
        self.config = ConfigParser.SafeConfigParser()
        self.config.read(self.file)

    def defaultValue(self, value):
        self.getdefault = value

    def read(self, sfilename):
        return self.config.read(sfilename)

    def sections(self):
        """ Sections of the Config File """
        return self.config.sections()

    def main_section(self, new_section):
        """ Change Section """
        self.main_section = new_section

    def options(self, new_section):
        """ Options from a NEW SECTION, that become Main_Section """
        self.main_section = new_section
        return self.config.options(self.main_section)

    def add_section(self, new_section):
        """ Add a New section """
        self.main_section = new_section
        self.config.add_section(self.main_section)

    # GET functions
    def get(self, section, option, defval = None):
        """ Get a VALUE of an option, of the SECTION"""
        self.main_section = section
        try:
            return self.config.get(self.main_section, option)
        except:
            if defval != None:
                return defval
            else:
                return self.getdefault
    def getboolean(self, section, option):
        """ GET a BOOLEAN Value of an OPTION of the SECTION """
        self.main_section = section
        try:
            return self.config.getboolean(self.main_section, option)
        except:
            return False
    def getfloat(self, section, option):
        """ GET a BOOLEAN Value of an OPTION of the SECTION """
        self.main_section = section
        try:
            return self.config.getfloat(self.main_section, option)
        except:
            return False
    def getint(self, section, option):
        """ GET a BOOLEAN Value of an OPTION of the SECTION """
        self.main_section = section
        try:
            return self.config.getint(self.main_section, option)
        except:
            return False
    def has_option(self, section,option):
        """ Exists OPTION in SECTION """
        self.main_section = section
        try:
            return self.config.has_option(self.main_section, option)
        except:
            return False

    # get FROM the Main_SECTION
    def options2(self):
        """ Options from Main_Section """
        return self.options(self.main_section)
    def get2(self, option):
        """ Get a VALUE of an option, of the MAIN_SECTION"""
        return self.get(self, self.main_section, option)
    def getboolean2(self, option):
        """ GET a BOOLEAN Value of an OPTION of the SECTION """
        return self.getboolean(self.main_section, option)
    def getint2(self, option):
        """ GET a BOOLEAN Value of an OPTION of the SECTION """
        return self.getint(self.main_section, option)
    def getfloat2(self, option):
        """ GET a BOOLEAN Value of an OPTION of the SECTION """
        return self.getfloat(self.main_section, option)
    def has_option2(self, option):
        """ Exists OPTION in MAIN_SECTION """
        return self.has_option(self.main_section, option)
    def has_section(self, section):
        try:
            return self.config.has_section(section)
        except:
            return False

    # Write Data to self.File
    def writedata(self):
        sf = open(self.file,"w") # Necesito el fichero INI "preparado" para grabar información
        self.config.write(sf)
        sf.close()
    def set(self, section, option, value = None, bSave = True):
        if self.config.has_section(section) == False:
            self.config.add_section(section)
        self.main_section = section
        self.config.set(self.main_section, option, value)
        if bSave:
            self.writedata()

    # Write OPTION-VALUE to MAIN_SECTION
    def set2(self, option, value = None, bSave = True):
        """ Set data on the MAIN_SECTION """
        self.set(self.main_section, option, value, bSave)

Características de mi ConfigParser advanced

La principales características de mi propuesta de ConfigParser son:

  • Una única clase que es capaz tanto de leer como escribir datos.
  • Si estoy trabajando con una única sección, tengo métodos para no tener que introducirla cada vez (aunque existen otros métodos para incluirlo como parámetro
  • Mejoras en preguntar si existen secciones y claves dentro de una sección
  • Control al insertar datos por si no existe una sección, añadirla primero

Supongo que para muchos no hubiera sido necesario crear una clase nueva, pero … a mi me sirve, y es lo que cuenta!