---
title: "Logging em Python — 2025 | Python Brasil"
url: "https://python.dev.br/blog/logging-em-python/"
markdown_url: "https://python.dev.br/blog/logging-em-python.MD"
description: "Domine o módulo logging em Python. Níveis, formatação, handlers e boas práticas profissionais. Aprenda agora!"
date: "2026-03-01"
author: "Equipe Python Brasil"
---

# Logging em Python — 2025 | Python Brasil

Domine o módulo logging em Python. Níveis, formatação, handlers e boas práticas profissionais. Aprenda agora!


O módulo `logging` é uma das ferramentas mais subutilizadas por desenvolvedores Python iniciantes e intermediários. Enquanto `print()` pode parecer suficiente durante o desenvolvimento, em produção ele é completamente inadequado. O logging profissional permite categorizar mensagens por severidade, direcionar logs para diferentes destinos, formatar saídas de maneira padronizada e desativar ou ativar mensagens sem alterar o código.

Neste artigo, vamos explorar o módulo `logging` do Python em profundidade, desde o uso básico até configurações avançadas para aplicações profissionais.

## Por que não usar print()?

Antes de mergulhar no `logging`, vale entender por que `print()` é insuficiente em projetos reais:

```python
# O problema com print()
print("Iniciando processamento...")          # Sem contexto temporal
print("ERRO: arquivo não encontrado")        # Sem severidade formal
print(f"Processando item {item}")            # Não pode ser desligado facilmente
print("DEBUG: valor da variável x =", x)     # Vai para produção por acidente
```

O `print()` mistura todas as mensagens em um único fluxo sem distinção de importância, sem timestamp, sem informação de origem e sem possibilidade de controle granular. O módulo `logging` resolve todos esses problemas.

## Configuração básica

O jeito mais rápido de começar com logging:

```python
import logging

# Configuração básica
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)

logger = logging.getLogger(__name__)

# Usando diferentes níveis
logger.debug("Variável x = 42")          # Não aparece (nível INFO configurado)
logger.info("Processamento iniciado")     # Aparece
logger.warning("Disco com 85% de uso")   # Aparece
logger.error("Falha na conexão com DB")  # Aparece
logger.critical("Sistema fora do ar")    # Aparece
```

Os cinco níveis de severidade, em ordem crescente, são: DEBUG, INFO, WARNING, ERROR e CRITICAL. Ao configurar o nível como INFO, todas as mensagens de nível INFO ou superior são exibidas, enquanto DEBUG é ignorado.

## Níveis de log e quando usá-los

Cada nível tem um propósito específico:

```python
import logging

logger = logging.getLogger("minha_app")

# DEBUG: informações detalhadas para diagnóstico
# Use para rastrear o fluxo do programa durante desenvolvimento
logger.debug("Consultando banco: SELECT * FROM users WHERE id = %s", user_id)

# INFO: confirmação de que as coisas estão funcionando
# Use para eventos normais e esperados
logger.info("Servidor iniciado na porta 8000")
logger.info("Usuário %s realizou login", username)

# WARNING: algo inesperado aconteceu, mas o programa continua
# Use para situações que merecem atenção
logger.warning("Tentativa de login com senha incorreta para %s", username)
logger.warning("API externa respondeu em %dms (limite: 500ms)", tempo)

# ERROR: o programa não conseguiu realizar uma operação
# Use quando algo falhou mas o sistema continua rodando
logger.error("Falha ao enviar e-mail para %s: %s", email, erro)

# CRITICAL: erro grave que pode impedir o programa de continuar
# Use para falhas que comprometem o sistema
logger.critical("Banco de dados principal inacessível")
```

## Handlers: direcionando logs

Handlers definem para onde as mensagens de log são enviadas. Você pode ter múltiplos handlers, cada um com seu próprio nível e formato:

```python
import logging
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler

def configurar_logging():
    """Configura logging com múltiplos handlers."""
    logger = logging.getLogger("minha_app")
    logger.setLevel(logging.DEBUG)

    # Formato detalhado para arquivo
    formato_arquivo = logging.Formatter(
        "%(asctime)s | %(name)s | %(levelname)-8s | %(filename)s:%(lineno)d | %(message)s"
    )

    # Formato simplificado para console
    formato_console = logging.Formatter(
        "%(asctime)s - %(levelname)-8s - %(message)s",
        datefmt="%H:%M:%S"
    )

    # Handler de console (INFO e acima)
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    console_handler.setFormatter(formato_console)

    # Handler de arquivo com rotação por tamanho
    arquivo_handler = RotatingFileHandler(
        "app.log",
        maxBytes=5_000_000,      # 5 MB por arquivo
        backupCount=5,           # Mantém 5 arquivos de backup
        encoding="utf-8"
    )
    arquivo_handler.setLevel(logging.DEBUG)
    arquivo_handler.setFormatter(formato_arquivo)

    # Handler separado para erros
    erro_handler = logging.FileHandler(
        "erros.log",
        encoding="utf-8"
    )
    erro_handler.setLevel(logging.ERROR)
    erro_handler.setFormatter(formato_arquivo)

    # Adicionando handlers ao logger
    logger.addHandler(console_handler)
    logger.addHandler(arquivo_handler)
    logger.addHandler(erro_handler)

    return logger

logger = configurar_logging()
logger.info("Sistema iniciado com sucesso")
logger.debug("Modo debug ativo")
logger.error("Exemplo de erro registrado")
```

Com essa configuração, mensagens DEBUG vão apenas para o arquivo `app.log`, mensagens INFO e acima aparecem no console e no arquivo, e erros são adicionalmente registrados em `erros.log`.

## Logging com contexto usando extras

Adicionar contexto às mensagens de log facilita a depuração:

```python
import logging

logger = logging.getLogger("api")

def processar_requisicao(request_id, usuario, endpoint):
    """Processa uma requisição com contexto nos logs."""
    extra = {"request_id": request_id, "usuario": usuario}

    logger.info(
        "Requisição recebida: %s %s",
        "GET", endpoint,
        extra=extra
    )

    try:
        # Simulação de processamento
        resultado = {"status": "ok", "dados": [1, 2, 3]}
        logger.info(
            "Requisição processada com sucesso: %d registros",
            len(resultado["dados"]),
            extra=extra
        )
        return resultado
    except Exception as e:
        logger.exception(
            "Erro ao processar requisição para %s",
            endpoint,
            extra=extra
        )
        return None
```

O método `logger.exception()` registra automaticamente o traceback completo da exceção, sendo muito mais informativo que `logger.error()` dentro de um bloco except.

## Configuração via dicionário

Para projetos maiores, a configuração via dicionário é mais organizada e flexível:

```python
import logging
import logging.config

CONFIG_LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "padrao": {
            "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
            "datefmt": "%Y-%m-%d %H:%M:%S"
        },
        "detalhado": {
            "format": "%(asctime)s | %(name)s | %(levelname)-8s | %(module)s:%(funcName)s:%(lineno)d | %(message)s"
        }
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "level": "INFO",
            "formatter": "padrao",
            "stream": "ext://sys.stdout"
        },
        "arquivo": {
            "class": "logging.handlers.RotatingFileHandler",
            "level": "DEBUG",
            "formatter": "detalhado",
            "filename": "aplicacao.log",
            "maxBytes": 10485760,
            "backupCount": 3,
            "encoding": "utf-8"
        }
    },
    "loggers": {
        "minha_app": {
            "level": "DEBUG",
            "handlers": ["console", "arquivo"],
            "propagate": False
        },
        "minha_app.banco": {
            "level": "WARNING",
            "handlers": ["console", "arquivo"],
            "propagate": False
        }
    },
    "root": {
        "level": "WARNING",
        "handlers": ["console"]
    }
}

logging.config.dictConfig(CONFIG_LOGGING)

# Usando loggers específicos
logger_app = logging.getLogger("minha_app")
logger_banco = logging.getLogger("minha_app.banco")

logger_app.info("Aplicação iniciada")
logger_banco.debug("Query executada")  # Não aparece (nível WARNING)
logger_banco.warning("Conexão lenta com o banco")
```

## Logging em módulos separados

Em projetos com múltiplos módulos, cada módulo deve criar seu próprio logger:

```python
# arquivo: servicos/usuario.py
import logging

logger = logging.getLogger(__name__)

class ServicoUsuario:
    def criar(self, nome, email):
        logger.info("Criando usuário: %s (%s)", nome, email)
        try:
            # Lógica de criação
            logger.info("Usuário %s criado com sucesso", nome)
            return True
        except Exception:
            logger.exception("Falha ao criar usuário %s", nome)
            return False

# arquivo: servicos/pedido.py
import logging

logger = logging.getLogger(__name__)

class ServicoPedido:
    def processar(self, pedido_id):
        logger.info("Processando pedido %s", pedido_id)
        # Lógica de processamento
```

Usar `__name__` como nome do logger cria automaticamente uma hierarquia baseada na estrutura de pacotes, facilitando a configuração de níveis diferentes para cada módulo.

## Boas práticas de logging

Para um sistema de logging profissional:

- **Use `__name__` como nome do logger**: cria hierarquia automática e facilita o controle.
- **Nunca use print() em produção**: substitua por logging com o nível adequado.
- **Use formatação lazy**: prefira `logger.info("Valor: %s", x)` em vez de `logger.info(f"Valor: {x}")`. A formatação lazy só processa a string se o log for realmente emitido.
- **Registre exceções com `exception()`**: dentro de blocos except, use `logger.exception()` para incluir o traceback.
- **Não logue dados sensíveis**: senhas, tokens e dados pessoais nunca devem aparecer em logs.
- **Configure rotação de arquivos**: use RotatingFileHandler ou TimedRotatingFileHandler para evitar que logs consumam todo o disco.
- **Estruture os logs**: em sistemas distribuídos, considere usar logging em formato JSON para facilitar a análise com ferramentas como ELK Stack.

## Conclusão

O módulo `logging` é uma ferramenta fundamental para qualquer aplicação Python profissional. Ele oferece flexibilidade para direcionar mensagens para diferentes destinos, controlar a verbosidade por módulo e formatar saídas de maneira padronizada. Investir tempo para configurar o logging adequadamente no início do projeto economiza muitas horas de depuração no futuro.

Como próximos passos, explore bibliotecas como `structlog` para logging estruturado, aprenda a integrar logs com ferramentas de monitoramento como Grafana e Prometheus, e estude como configurar alertas automáticos baseados em padrões de erro nos seus logs.

> **Logging em outras linguagens**: se você trabalha em ambientes multilinguagem, vale conhecer o <a href="https://golang.com.br/blog/slog-go-logging-estruturado/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">slog do Go</a> — o pacote de logging estruturado da biblioteca padrão que segue uma filosofia similar ao `structlog` do Python, com logs em formato JSON nativamente.
