A Importância de Usar um Módulo de Logging
Em sistemas de software complexos, imprimir mensagens de status diretamente no console usando print() é uma prática inadequada. Essas instruções podem ser esquecidas no código e poluem a saída padrão, dificultando a leitura de outros dados. O módulo logging do Python oferece uma estrutura flexível e poderosa para registrar informações do aplicativo de forma controlada.
As principais vantagens do logging incluem:
- Controle granular sobre a severidade das mensagens (níveis).
- Capacidade de direcionar a saída para diferentes destinos (console, arquivos, sockets, etc.).
- Configuração de formatos customizados para as mensagens.
- Possibilidade de filtrar mensagens com base em critérios específicos.
Arquitetura do Logging
O framework é composto por quatro pilares fundamentais:
- Logger: A interface principal que o código da aplicação invoca para criar uma mensagem de log.
- Handler: Responsável por enviar a mensagem do logger para o destino apropriado (console, arquivo, etc.).
- Filter: Provê um mecanismo para decidir de forma granular quais mensagens de log devem ser efetivamente registradas.
- Formatter: Especifica a estrutura final e o layout da mensagem de log que será impressa.
Níveis de Severidade
O Python define cinco níveis de severidade, do menos crítico ao mais grave, que permitem categorizar as mensagens:
| Nível | Função Correspondente | Descrição |
|---|---|---|
| DEBUG | logging.debug() | Informações detalhadas, tipicamente úteis apenas para diagnóstico. |
| INFO | logging.info() | Confirmação de que as coisas estão funcionando conforme o esperado. |
| WARNING | logging.warning() | Indicação de que algo inesperado aconteceu, ou que um problema iminente pode ocorrer. |
| ERROR | logging.error() | Devido a um problema mais grave, o software não conseguiu executar uma função. |
| CRITICAL | logging.critical() | Um erro grave, indicando que o próprio programa pode não conseguir continuar rodando. |
Tanto o Logger quanto cada Handler podem ter seu nível de severidade configurado. Mensagens com um nível inferior ao definido serão ignoradas.
Gerenciamento do Logging
É possível desativar temporariamente todos os logs abaixo de um certo nível usando logging.disable(). Para desativar completamente a saída de logs durante a depuração ou produção, basta chamar:
import logging
logging.disable(logging.CRITICAL)
Para direcionar a saída para um arquivo em vez do console, configure o parâmetro filename no basicConfig:
logging.basicConfig(filename='aplicativo.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
Configuração Avançada via Dicionário
Para configurações mais complexas, como enviar logs simultaneamente para o console e um arquivo, com codificação e rotação específicas, a abordagem mais flexível é usar um dicionário de configuração.
Este dicionário define formatos, handlers e a hierarquia dos loggers.
import logging.config
# Definição dos formatos
FMT_PADRAO = '[%(asctime)s][%(levelname)s][%(name)s:%(lineno)d] %(message)s'
FMT_SIMPLE = '%(asctime)s - %(levelname)s - %(message)s'
# Configuração completa em dicionário
config_registros = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'padrao': {'format': FMT_PADRAO},
'simples': {'format': FMT_SIMPLE},
},
'handlers': {
'console_saida': {
'class': 'logging.StreamHandler',
'level': 'INFO',
'formatter': 'simples',
'stream': 'ext://sys.stdout',
},
'arquivo_saida': {
'class': 'logging.handlers.RotatingFileHandler',
'level': 'DEBUG',
'formatter': 'padrao',
'filename': 'logs/registro.log',
'maxBytes': 10485760, # 10MB
'backupCount': 3,
'encoding': 'utf-8',
},
},
'loggers': {
'': { # Logger raiz
'handlers': ['console_saida', 'arquivo_saida'],
'level': 'DEBUG',
'propagate': True,
},
'modulos.usuarios': {
'handlers': ['arquivo_saida'],
'level': 'INFO',
'propagate': False,
}
}
}
# Carregar a configuração
logging.config.dictConfig(config_registros)
# Obter e usar um logger
logger_aplicacao = logging.getLogger('modulos.usuarios')
logger_aplicacao.info('Ação do usuário registrada com sucesso.')
logger_aplicacao.debug('Esta mensagem de debug não será gravada no arquivo de log de usuários.')