configparser: leia e grave arquivos INI

Atualizado em: 20/08/2026
Tempo de leitura: 6 minutos
Diagrama de arquivos e sistema representando configurações INI com configparser no Python

O módulo configparser no Python lê e grava arquivos de configuração no estilo INI, organizados em seções, opções e valores textuais. Ele é adequado para aplicações desktop, ferramentas de linha de comando, scripts administrativos e programas que precisam permitir ajustes simples sem exigir JSON ou YAML.

O formato INI não possui uma especificação única e universal. Cada aplicação pode adotar regras diferentes para comentários, maiúsculas, delimitadores, valores vazios e interpolação. Por isso, configure o parser explicitamente e documente o dialeto aceito.

Crie um arquivo INI básico

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

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

Cada cabeçalho entre colchetes define uma seção. As opções usam = ou : como delimitador por padrão.

Leia a configuração

import configparser

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

if not lidos:
    raise FileNotFoundError("app.ini não foi carregado")

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

read() ignora silenciosamente arquivos que não consegue abrir e devolve a lista dos que foram lidos. Se um arquivo é obrigatório, verifique o retorno ou use read_file() com um handle já aberto.

Todos os valores são strings

O parser não infere tipos automaticamente. Use getint(), getfloat() e getboolean().

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

getboolean() reconhece valores como yes/no, true/false, on/off e 1/0. Não use bool("false"), pois qualquer string não vazia é verdadeira.

Use fallbacks corretamente

No proxy de uma seção, o segundo argumento de get() é o fallback:

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

Na API do parser, use a palavra-chave fallback:

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

Valores da seção DEFAULT têm prioridade sobre o fallback. Isso pode surpreender quando uma opção parece ausente na seção, mas é herdada.

Defina valores padrão

[DEFAULT]
timeout = 10
retries = 3

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

[worker]
retries = 5

As opções de DEFAULT ficam visíveis em todas as seções. Remover uma sobrescrita faz o valor padrão reaparecer; ele não pertence fisicamente à seção.

Leia vários arquivos em camadas

Arquivos lidos depois sobrescrevem opções conflitantes, mas preservam as demais.

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

Uma arquitetura comum usa defaults versionados, configuração do servidor e overrides do usuário. Não use arquivos opcionais para parâmetros críticos sem validar que os valores essenciais estão presentes.

Use read_file para arquivos obrigatórios

from pathlib import Path

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

Erros de sintaxe e abertura são propagados. O parâmetro source melhora a mensagem de diagnóstico.

Leia strings e dicionários

read_string() é útil em testes e conteúdo recebido de uma fonte controlada.

config.read_string("""
[servico]
url = https://example.com
""", source="configuração embutida")

read_dict() carrega uma estrutura de mapeamentos e converte valores para texto.

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

Entenda maiúsculas e minúsculas

Por padrão, nomes de seções diferenciam maiúsculas, mas opções não. As chaves são normalizadas para minúsculas por optionxform().

config = configparser.ConfigParser()
config.read_string("""
[Secao]
MinhaChave = valor
""")
print(list(config["Secao"]))
# ['minhachave']

Para preservar a caixa:

config.optionxform = str

Faça isso antes de ler dados. A função de transformação deve ser idempotente.

Interpolação básica

O ConfigParser usa BasicInterpolation por padrão.

[caminhos]
base = /opt/minhaapp
logs = %(base)s/logs
cache = %(base)s/cache

Para incluir um caractere percentual literal, escreva %%. A interpolação acontece quando o valor é obtido, não durante a leitura.

Interpolação estendida

ExtendedInterpolation usa a sintaxe ${seção:opção} e permite referências entre seções.

from configparser import ConfigParser, ExtendedInterpolation

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

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

Use $$ para um cifrão literal. Ciclos e referências ausentes geram exceções de interpolação.

Desative a interpolação quando necessário

Valores como padrões, templates e senhas podem conter % ou $. Se a interpolação não faz parte do formato:

config = configparser.ConfigParser(interpolation=None)

Também é possível usar get(..., raw=True) para uma leitura específica.

Conversores personalizados

O parâmetro converters cria novos métodos get*.

from pathlib import Path

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

pasta = config["logs"].getpath("arquivo")
origens = config["cors"].getlista("origens")

Conversão não é validação completa. Verifique faixas, extensões, existência, permissões e regras de negócio após converter.

Personalize valores booleanos

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

Um vocabulário customizado pode facilitar arquivos localizados, mas reduz portabilidade. Documente os valores aceitos.

Arquivos com opções sem valor

Alguns formatos usam flags sem delimitador.

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

Essas opções retornam None. No Python recente, continuar uma opção sem valor com linha indentada gera MultilineContinuationError.

Seções sem nome

Python 3.13 adicionou suporte opcional a uma seção inicial sem cabeçalho.

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

[outra]
x = 1
""")
valor = config[configparser.UNNAMED_SECTION]["chave"]

Ative o recurso apenas quando precisar compatibilidade com um formato existente.

Comentários e valores multilinha

Por padrão, # e ; iniciam comentários em linhas próprias. Comentários inline ficam desativados porque não existe escape confiável para os prefixos.

Valores multilinha precisam ser indentados além da chave:

[mensagem]
texto = primeira linha
    segunda linha
    terceira linha

Quando arquivos são editados por pessoas, considere empty_lines_in_values=False para reduzir ambiguidades visuais.

Modo estrito

strict=True, padrão atual, rejeita seções e opções duplicadas dentro da mesma fonte.

Essa validação captura erros de digitação e colisões causadas pela normalização de caixa. Mantenha-a ativa em novos projetos.

Trate exceções de forma clara

try:
    with open("app.ini", encoding="utf-8") as arquivo:
        config.read_file(arquivo)
except configparser.MissingSectionHeaderError as erro:
    raise RuntimeError("Arquivo sem cabeçalho de seção") from erro
except configparser.DuplicateOptionError as erro:
    raise RuntimeError("Opção duplicada") from erro
except configparser.InterpolationError as erro:
    raise RuntimeError("Interpolação inválida") from erro

Inclua fonte e linha no diagnóstico, mas não registre valores secretos.

Grave a configuração

from pathlib import Path

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

Todos os valores devem ser strings. No Python 3.14, write() gera InvalidWriteError se a representação não puder ser lida corretamente depois.

Escreva de forma atômica

Não sobrescreva diretamente um arquivo importante. Grave em um arquivo temporário no mesmo diretório, faça flush(), sincronize e substitua com os.replace().

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 temp:
    config.write(temp)
    temp.flush()
    os.fsync(temp.fileno())
    temporario = temp.name
os.replace(temporario, destino)

Controle permissões e proprietário. Em escrita concorrente, use locking ou um serviço central de configuração.

Comentários não são preservados

Ao ler e escrever novamente, comentários e formatação original são perdidos. Se usuários mantêm documentação importante no arquivo, evite reescrevê-lo automaticamente ou use uma biblioteca que preserve o layout.

Não guarde segredos no INI

Arquivos INI são texto simples. Senhas, tokens e chaves devem vir de um gerenciador de segredos, variável de ambiente protegida ou credencial do sistema. Se um segredo precisar ser referenciado, armazene apenas seu identificador.

O guia de site no Python explica caminhos de instalação e ambientes; importlib.resources ajuda a distribuir defaults dentro de pacotes; e fileinput no Python trata processamento de vários arquivos.

Valide depois de ler

def carregar_servidor(config):
    porta = config["servidor"].getint("porta")
    if not 1 <= porta <= 65535:
        raise ValueError("porta fora da faixa")

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

    return host, porta

O parser garante estrutura e conversões básicas; seu aplicativo deve validar semântica.

ConfigParser versus TOML e JSON

INI é simples e amigável para configurações pequenas. TOML possui especificação mais rigorosa e tipos nativos; JSON é interoperável, mas não aceita comentários. Escolha o formato pela complexidade, ecossistema e necessidade de edição humana.

Boas práticas

  • Use UTF-8 explicitamente.
  • Mantenha strict=True.
  • Verifique arquivos obrigatórios.
  • Defina o comportamento de caixa.
  • Desative interpolação se não for necessária.
  • Valide valores após converter.
  • Escreva atomicamente.
  • Não armazene segredos.

Conclusão

O configparser no Python oferece uma interface madura para configurações INI, com seções, defaults, camadas, interpolação e conversores. Ele funciona bem quando o formato permanece simples e claramente documentado.

Consulte a documentação oficial do configparser e a documentação do tomllib.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Desenvolvedor configurando servidor HTTPS e certificado TLS com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    HTTPSServer: crie servidor HTTPS local no Python

    Aprenda HTTPSServer no Python para servir HTTPS localmente, configurar certificados, usar threads e entender limites de segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    08/10/2026
    Arquivos protegidos representando extração segura de TAR com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    tarfile extraction_filter: extraia TAR com segurança

    Aprenda tarfile extraction_filter no Python para extrair arquivos TAR com validação, segurança e controle de caminhos.

    Ler mais

    Tempo de leitura: 6 minutos
    08/10/2026
    Código Python exibindo avisos controlados com catch_warnings
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    catch_warnings: capture warnings em testes Python

    Aprenda catch_warnings no Python para capturar, testar e controlar avisos com filtros específicos e segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código Python representando referências persistentes do pickle
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pickle persistent_id: serialize referências externas

    Aprenda pickle persistent_id no Python para serializar referências externas com IDs estáveis, validação, segurança e compatibilidade.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código binário representando buffers e memória no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    memoryview.count: conte valores sem copiar buffers

    Aprenda memoryview.count no Python para contar bytes e valores em buffers sem cópias, com formatos, limites e boas práticas.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026
    Código Python com anotações de tipos
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    annotationlib: evite imports circulares em anotações

    Aprenda annotationlib no Python para ler anotações adiadas, evitar imports circulares e criar ferramentas de introspecção seguras.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026