configparser en Python: archivos INI

Publicado el: 16/08/2026
Tempo de leitura: 5 minutos
Diagrama de archivos y sistema que representa configuración INI con configparser en Python

El módulo configparser en Python lee y escribe archivos de configuración con estilo INI, organizados en secciones, opciones y valores de texto. Es apropiado para aplicaciones de escritorio, herramientas de línea de comandos, scripts administrativos y programas que necesitan ajustes editables por personas sin recurrir a JSON, YAML o una base de datos.

INI no tiene una única especificación universal. Las aplicaciones difieren en reglas para comentarios, mayúsculas, delimitadores, opciones vacías, valores multilínea e interpolación. Configura el parser deliberadamente y documenta el dialecto aceptado.

Crea un archivo INI básico

[servidor]
host = 127.0.0.1
puerto = 8080
debug = false

[logs]
nivel = INFO
archivo = logs/app.log

Cada encabezado entre corchetes define una sección. Las opciones utilizan = o : como delimitadores por defecto.

Lee la configuración

import configparser

config = configparser.ConfigParser()
leidos = config.read("app.ini", encoding="utf-8")

if not leidos:
    raise FileNotFoundError("app.ini no fue cargado")

host = config["servidor"]["host"]
puerto = config["servidor"].getint("puerto")
debug = config["servidor"].getboolean("debug")

read() ignora silenciosamente archivos que no puede abrir y devuelve la lista de nombres procesados. Comprueba el resultado para archivos obligatorios o usa read_file() con un handle abierto.

Todos los valores son strings

El parser no infiere tipos. Usa getint(), getfloat() y getboolean().

timeout = config["servidor"].getfloat("timeout", fallback=5.0)
workers = config["servidor"].getint("workers", fallback=4)
activo = config["servidor"].getboolean("activo", fallback=True)

getboolean() reconoce yes/no, true/false, on/off y 1/0. No uses bool("false"), porque toda string no vacía es verdadera.

Usa fallback correctamente

En el proxy de sección, el segundo argumento de get() es el fallback:

nivel = config["logs"].get("nivel", "INFO")

En la API del parser, utiliza la palabra clave:

nivel = config.get("logs", "nivel", fallback="INFO")

Los valores heredados de DEFAULT tienen prioridad sobre el fallback, incluso cuando la opción no aparece físicamente en la sección.

Define valores predeterminados

[DEFAULT]
timeout = 10
reintentos = 3

[api]
url = https://api.example.com

[worker]
reintentos = 5

Las opciones de DEFAULT son visibles en todas las secciones. Eliminar una sobrescritura hace reaparecer el valor predeterminado.

Combina archivos por capas

Los archivos leídos más tarde sobrescriben las opciones conflictivas y conservan las demás.

config.read(
    ["defaults.ini", "sitio.ini", "usuario.ini"],
    encoding="utf-8",
)

Un diseño común utiliza defaults versionados, configuración del servidor y overrides personales. Después de cargar todas las capas, valida las opciones obligatorias.

Usa read_file para archivos obligatorios

from pathlib import Path

ruta = Path("defaults.ini")
with ruta.open(encoding="utf-8") as archivo:
    config.read_file(archivo, source=str(ruta))

Los errores de apertura y sintaxis se propagan. El parámetro source mejora los diagnósticos.

Lee strings y diccionarios

read_string() es útil en tests y configuraciones embebidas controladas.

config.read_string("""
[servicio]
url = https://example.com
""", source="defaults embebidos")

read_dict() carga mappings anidados y convierte claves y valores a texto.

config.read_dict({
    "servidor": {"puerto": 8080, "debug": False},
})

Mayúsculas y minúsculas

Los nombres de sección distinguen mayúsculas, pero las opciones no. optionxform() convierte las claves a minúsculas.

config = configparser.ConfigParser()
config.read_string("""
[Seccion]
MiClave = valor
""")
print(list(config["Seccion"]))
# ['miclave']

Para conservar la forma original:

config.optionxform = str

Configúralo antes de leer. Una transformación personalizada debe ser idempotente.

Interpolación básica

ConfigParser usa BasicInterpolation por defecto.

[rutas]
base = /opt/miapp
logs = %(base)s/logs
cache = %(base)s/cache

Escribe %% para un porcentaje literal. La sustitución ocurre al obtener el valor.

Interpolación extendida

ExtendedInterpolation utiliza ${sección:opción} y permite referencias entre secciones.

from configparser import ConfigParser, ExtendedInterpolation

config = ConfigParser(interpolation=ExtendedInterpolation())
[comun]
raiz = /srv/app

[logs]
dir = ${comun:raiz}/logs

Usa $$ para un cifrón literal. Referencias ausentes y ciclos generan excepciones.

Desactiva la interpolación cuando sea necesario

Contraseñas, templates, expresiones regulares y fragmentos shell pueden contener % o $. Si el formato no utiliza sustitución:

config = configparser.ConfigParser(interpolation=None)

En una lectura puntual, usa raw=True.

Añade conversores personalizados

El argumento converters crea nuevos métodos get*.

from pathlib import Path

config = configparser.ConfigParser(
    converters={
        "path": Path,
        "lista": lambda valor: [x.strip() for x in valor.split(",")],
    },
)

ruta_log = config["logs"].getpath("archivo")
origines = config["cors"].getlista("origines")

Convertir no equivale a validar. Comprueba rangos, extensiones, raíces permitidas, existencia y reglas de negocio.

Personaliza valores booleanos

config.BOOLEAN_STATES = {
    "habilitado": True,
    "deshabilitado": False,
}

Un vocabulario localizado puede mejorar legibilidad, pero reduce portabilidad. Documenta las formas aceptadas.

Opciones sin valor

Algunos dialectos usan flags sin delimitador.

config = configparser.ConfigParser(allow_no_value=True)
[recursos]
modo_seguro
auditoria

Estas opciones devuelven None. En Python reciente, continuar una opción sin valor con una línea indentada genera MultilineContinuationError.

Secciones sin nombre

Python 3.13 añadió soporte opcional para opciones antes del primer encabezado.

config = configparser.ConfigParser(allow_unnamed_section=True)
config.read_string("""
clave = valor

[otra]
x = 1
""")
valor = config[configparser.UNNAMED_SECTION]["clave"]

Actívalo únicamente para compatibilidad con un formato existente.

Comentarios y valores multilínea

Por defecto, # y ; introducen comentarios en líneas propias. Los comentarios inline están deshabilitados porque no existe un escape fiable.

Los valores multilínea deben tener mayor indentación:

[mensaje]
texto = primera línea
    segunda línea
    tercera línea

Para archivos editados por personas, considera empty_lines_in_values=False para reducir ambigüedad.

Mantén strict activo

strict=True, valor predeterminado actual, rechaza secciones y opciones duplicadas dentro de una fuente. Detecta errores de escritura y colisiones causadas por la normalización de caja.

Trata errores con claridad

try:
    with open("app.ini", encoding="utf-8") as archivo:
        config.read_file(archivo)
except configparser.MissingSectionHeaderError as error:
    raise RuntimeError("Falta un encabezado de sección") from error
except configparser.DuplicateOptionError as error:
    raise RuntimeError("Opción duplicada") from error
except configparser.InterpolationError as error:
    raise RuntimeError("Interpolación inválida") from error

Incluye fuente y línea en el diagnóstico, pero nunca registres valores secretos.

Escribe configuración

from pathlib import Path

config["servidor"]["puerto"] = "9090"
with Path("app.ini").open("w", encoding="utf-8") as archivo:
    config.write(archivo)

Todos los valores deben ser strings. En Python 3.14, write() genera InvalidWriteError cuando la representación no podría leerse correctamente.

Escribe de forma atómica

No sobrescribas directamente un archivo crítico. Escribe en un temporal del mismo directorio, sincroniza y sustituye el destino.

import os
from pathlib import Path
from tempfile import NamedTemporaryFile

destino = Path("app.ini")
with NamedTemporaryFile("w", encoding="utf-8", dir=destino.parent, delete=False) as temporal:
    config.write(temporal)
    temporal.flush()
    os.fsync(temporal.fileno())
    ruta_temporal = temporal.name
os.replace(ruta_temporal, destino)

Controla permisos y usa locking o un servicio central cuando existan varios escritores.

Los comentarios no se conservan

Leer y escribir nuevamente elimina comentarios y formato original. Si los usuarios mantienen explicaciones importantes, evita reescrituras automáticas o utiliza una biblioteca que preserve el layout.

No guardes secretos en INI

Los archivos INI son texto plano. Contraseñas, tokens y claves privadas deben proceder de un gestor de secretos, variable de entorno protegida o almacén del sistema. Guarda solo el identificador del secreto.

La guía de site en Python explica rutas y entornos; importlib.resources permite distribuir defaults dentro del paquete; y fileinput en Python ayuda con múltiples archivos.

Valida después de leer

def cargar_servidor(config):
    puerto = config["servidor"].getint("puerto")
    if not 1 <= puerto <= 65535:
        raise ValueError("puerto fuera de rango")

    host = config["servidor"].get("host", "127.0.0.1").strip()
    if not host:
        raise ValueError("host vacío")

    return host, puerto

El parser valida estructura y conversiones básicas; la aplicación debe validar semántica.

ConfigParser, TOML y JSON

INI es amigable para configuraciones pequeñas. TOML posee especificación más estricta y tipos nativos. JSON es interoperable, pero no acepta comentarios. Elige según complejidad, ecosistema y necesidad de edición humana.

Buenas prácticas

  • Abre archivos explícitamente como UTF-8.
  • Mantén strict=True.
  • Comprueba archivos obligatorios.
  • Define el comportamiento de mayúsculas.
  • Desactiva interpolación si no la utilizas.
  • Valida cada valor convertido.
  • Escribe actualizaciones de forma atómica.
  • Mantén secretos fuera del INI.

Conclusión

configparser en Python proporciona una interfaz madura para configuración INI con secciones, defaults, capas, interpolación, conversores y acceso como mapping. Funciona mejor cuando el dialecto aceptado es simple y está documentado.

Consulta la documentación oficial de configparser y la documentación de tomllib.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Módulo de memoria RAM que representa gestión de objetos con gc en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    gc en Python: controla el recolector

    Aprende gc en Python para controlar la recolección cíclica, inspeccionar objetos, diagnosticar memoria y observar pausas.

    Ler mais

    Tempo de leitura: 7 minutos
    16/08/2026
    Líneas de código fuente que representan rastreo de ejecución con trace en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    trace en Python: rastrea ejecución

    Aprende trace en Python para contar líneas, seguir la ejecución, listar funciones, combinar cobertura y filtrar módulos.

    Ler mais

    Tempo de leitura: 6 minutos
    16/08/2026
    Portátil con gráficos de rendimiento que representa análisis de perfiles con pstats en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pstats en Python: analiza perfiles

    Aprende pstats en Python para ordenar, filtrar, combinar e interpretar perfiles de cProfile, callers, callees y tiempos acumulados.

    Ler mais

    Tempo de leitura: 5 minutos
    15/08/2026
    Portátil con código que representa ejemplos ejecutables probados con doctest en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    doctest en Python: prueba ejemplos

    Aprende doctest en Python para ejecutar ejemplos en docstrings y archivos, normalizar salidas e integrar documentación con CI.

    Ler mais

    Tempo de leitura: 5 minutos
    15/08/2026
    Código en pantalla que representa navegación de clases y funciones con pyclbr en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pyclbr en Python: inspecciona módulos

    Aprende pyclbr en Python para listar clases, funciones, métodos y definiciones anidadas sin importar ni ejecutar el módulo.

    Ler mais

    Tempo de leitura: 5 minutos
    15/08/2026
    Monitor con código binario que representa instrucciones opcode del bytecode de Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    opcode en Python: explora el bytecode

    Aprende opcode en Python para mapear instrucciones de bytecode, argumentos, saltos, caches y efectos de pila mediante dis.

    Ler mais

    Tempo de leitura: 5 minutos
    15/08/2026