Archivos de configuración con el módulo configparser



Versión: Python 2.6, 2.7, 3.x

Introducción

El módulo ConfigParser o configparser (según la versión, 2 o 3, respectivamente) nos provee una manera sencilla de acceder a archivos de configuración. Resulta útil a la hora de escribir programas en Python los cuales pueden ser modificados fácilmente por el usuario.

El formato es más compacto y legible que XML y, según la plataforma, puede encontarse con las extensiones .ini, .cfg, .conf, entre otras. Consiste en secciones, indicandose en corchetes, y entradas, especificando primero el nombre y luego el valor. Por ejemplo, el siguiente archivo de configuración, «tema.cfg» (o «tema.ini», como gustes), podría corresponder a un programa con temas configurables que almacena el actual:

[TEMA]
nombre="Tema Oscuro"
version=1.0
autor="Recursos Python"
votos=50

Una sección TEMA, con 4 valores (nombre, version, autor y votos). Nótese el uso del caracter ‘=’ (igual) para llevar a cabo la asignación del valor. El caracter ‘:’ (dos puntos) también puede ser utilizado.

[TEMA]
nombre:"Tema Oscuro"
version:1.0
autor:"Recursos Python"
votos:50

Si se desea instertar un comentario, las líneas que comiencen con ‘;’ (punto y coma) serán ignoradas. Recuérdese siempre añadir un espacio antes del caracter de comentario para que sea interpretado como tal. De lo contrario, será tomado en cuenta como parte del valor, en caso que se encuentre en una asignación.

Antes de comenzar con el código, se podría agregar una segunda sección «TEMA2», el cual podría ser cargado por el supuesto programa en caso de no encontrarse el anterior.

[TEMA2]
nombre="Tema Verde"
version=2.2
autor="Recursos Python"
votos=22

Incluso se podría añadir «GENERAL» en donde se especifique el número de temas, al comienzo del archivo.

[GENERAL]
temas=2

Por lo que el archivo quedaría de la siguiente manera:

[GENERAL]
temas=2
[TEMA]
nombre="Tema Oscuro"
version=1.0
autor="Recursos Python"
votos=50
[TEMA2]
nombre="Tema Verde"
version=2.2
autor="Recursos Python"
votos=22

Los archivos de configuración pueden contener tantas secciones y valores como se desee.

Aplicación

El módulo consta de tres clases:

  • RawConfigParser
  • ConfigParser
  • SafeConfigParser

ConfigParser hereda de RawConfigParser y, a su vez, SafeConfigParser de ConfigParser.

Por ahora, ConfigParser nos provee todas las herramientas necesarias para tratar con el archivo. Sin embargo, según la documentación oficial preferiríamos usar SafeConfigParser si no necesitamos compatibilidad con versiones antiguas de Python.

Empecemos importando la clase que necesitamos:

try:
    from ConfigParser import ConfigParser
except ImportError:
    # Python 3
    from configparser import ConfigParser

O simplemente from ConfigParser import ConfigParser o from configparser import ConfigParser según la versión de Python con la que cuentes. Siempre es preferible importar únicamente lo que vamos a utilizar.

Una vez importada la clase, prosigamos creando una instancia de la misma e indicandole el archivo en el cual vamos a trabajar.

config = ConfigParser()
config.read("tema.cfg")

El método read() recibe como parámetro el nombre de un archivo, o una lista que contenga varios.

Seguiremos imprimiendo en pantalla las secciones del archivo, mediante la función sections() que nos devuelve una lista conteniendo el nombre de cada una de ellas.

sections = config.sections()
print("%d secciones:" % len(sections))  # Cantidad de secciones

# Imprimimos cada una de ellas
for section in config.sections():
    print(section)

Leer la cantidad de temas contenidos en el archivo.

themes_count = config.get("GENERAL", "temas")

La función get() recibe como primer parámetro el nombre de la sección y como segundo, el ítem, retornando su valor. En este caso devolverá «2», ya que es el valor que hemos especificado para el ítem «temas» de la sección «GENERAL». Nótese que, al tratarse de un archivo de texto, el valor de retorno es una cadena. Por lo tanto, preferiblemente usaremos la función getint() que hará el trabajo de conversión por nosotros:

themes_count = config.getint("GENERAL", "temas")

Y para comprobar que sea un entero:

print(themes_count, type(themes_count))

Imprime:

2 <type 'int'>

Tal como esta función, existen los métodos getfloat() y getboolean(), que retornan un valor del tipo float y boolean, respectivamente.

La función items() recibe una sección y devuelve los ítems con sus respectivos valores.

for item in config.items("TEMA"):
    print(item[0], item[1])

Cada uno de los elementos en la lista retornada por el método es una tupla, la cual consiste en el nombre del ítem en primer lugar y su correspondiente valor en el segundo. Por lo tanto, el código anterior imprime:

nombre "Tema Oscuro"
version 1.0
autor "Recursos Python"
votos 50

Para imprimir todos los valores de todas las secciones del archivo:

for section in config.sections():
    print("\n[%s]" % section)
    for item in config.items(section):
        print(item[0], ":", item[1])

De esta manera, section tendrá el valor de cada una de las secciones, e item el valor de cada uno de los ítems de dicha sección. El caracter ‘\n’ (nueva línea) es simplemente para optimizar la visualización de los datos.

Por último, la función set() nos permite alterar el valor de cualquier ítem.

config.set("GENERAL", "temas", themes_count + 1)
config.set("TEMA", "nombre", "Tema Claro")
config.set("TEMA", "version", 1.2)
config.set("TEMA", "autor", "Desconocido")
config.set("TEMA", "votos", 51)

Así editamos una sección existente. En el caso que queramos crear una nueva, la función add_section() nos lo permite.

config.add_section("TEMA3")
config.set("TEMA3", "nombre", "Tema Nuevo")
config.set("TEMA3", "version", 0.1)
config.set("TEMA3", "autor", "Python")
config.set("TEMA3", "votos", 1)

Al igual que remove_section() nos permite eliminarla.

config.remove_section("TEMA3")

O simplemente eliminar un ítem:

config.remove_option("TEMA3", "votos")

Por último, para guardar los cambios, usamos el método write.

with open("tema.cfg", "w") as f:
    config.write(f)

Código completo:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    from ConfigParser import ConfigParser
except ImportError:
    # Python 3
    from configparser import ConfigParser

# Creamos una instancia de la clase y abrimos el archivo
config = ConfigParser()
config.read("tema.cfg")

# Cantidad de secciones
sections = config.sections() 
print("%d secciones:" % len(sections))

# Imprimimos cada una de ellas
for section in sections:
    print(section)

# Leemos la cantidad de temas
themes_count = config.getint("GENERAL", "temas")
print(themes_count, type(themes_count))

# Modificamos el tema principal
config.set("GENERAL", "temas", themes_count + 1)
config.set("TEMA", "nombre", "Tema Claro")
config.set("TEMA", "version", 1.2)
config.set("TEMA", "autor", "Desconocido")
config.set("TEMA", "votos", 51)

# Agregamos un nuevo tema (sección)
config.add_section("TEMA3")
config.set("TEMA3", "nombre", "Tema Nuevo")
config.set("TEMA3", "version", 0.1)
config.set("TEMA3", "autor", "Python")
config.set("TEMA3", "votos", 1)

# Removemos el ítem "votos" de la sección "TEMA2"
config.remove_option("TEMA2", "votos")

# Guardamos los cambios
with open("tema.cfg", "w") as f:
    config.write(f)

Comentarios

Al momento de usar comentarios, ten en cuenta lo siguiente. Prueba este código:

config = ConfigParser()
config.read("test.cfg")

print(config.getint("PRUEBA", "dato"))

Y el archivo «test.cfg»:

[PRUEBA]
dato=50

Verás que imprime en pantalla ’50’ (sin comillas). Como recordarás, el caracter ‘;’ (punto y coma) permite instertar comentarios. Intenta editando test.cfg de la siguiente manera:

[PRUEBA]
dato=50;Comentario

Corre el código nuevamente, y arrojará el siguiente error:

ValueError: invalid literal for int() with base 10: '50;Comentario'

Para evitar esto, recuerda siempre colocar un espacio antes del ‘;’.

[PRUEBA]
dato=50 ;Comentario

Corre el programa y funcionará correctamente.

Para obtener más información y detalles de cada una de las funciones y clases, visita la documentación oficial del módulo.



Deja una respuesta