Estou usando o módulo de registro Python e gostaria de desativar as mensagens de log impressas pelos módulos de terceiros que importei. Por exemplo, estou usando algo como o seguinte:
logger = logging.getLogger()
logger.setLevel(level=logging.DEBUG)
fh = logging.StreamHandler()
fh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s')
fh.setFormatter(fh_formatter)
logger.addHandler(fh)
Isso imprime minhas mensagens de depuração quando eu faço um logger.debug ("minha mensagem!"), Mas também imprime as mensagens de depuração de qualquer módulo que eu importo (como solicitações e várias outras coisas).
Gostaria de ver apenas as mensagens de log dos módulos nos quais estou interessado. É possível fazer com que o módulo de log faça isso?
Idealmente, eu gostaria de ser capaz de dizer ao logger para imprimir mensagens de "ModuleX, ModuleY" e ignorar todas as outras.
Observei o seguinte, mas não quero ter que desabilitar / habilitar o registro antes de cada chamada para uma função importada: registro - como ignorar os registros do módulo importado?
__name__
r, mas ainda vejo os logs dos módulos importados. Estou tentando configurar o log com um arquivo de configuração ini. O que devo fazer para isso?__name__
também não funcionou para mim. Talvez porque estou usando um script autônomo e não um "módulo"? O que funcionou para mim foi configurar o log de módulos importados (matpplotlib
no meu caso) vialogging.getLogger("matplotlib").setLevel(logging.WARNING)
e para meu script vialogging.basicConfig
.logger.debug
vez delogging.debug
". É um erro fácil de cometer ao usar o log em vez do logger, mas usurpa todas as configurações inteligentes que você deseja definir. Passei as últimas horas vivendo isso!logger = logging.getLogger('package.my_module')
chamadas e your couldlogger.debug/warning
, sem configuração de níveis de registro ou manipuladores. Ao escrever o aplicativo binário lá, você deve decidir o nível dos vários logs e dos manipuladores. Bibliotecas que contêm configuração de registro sempre serão um problema.logging.getLogger(__name__)
.Se você for usar o
logging
pacote python , é uma convenção comum definir um logger em cada módulo que o usa.Muitos pacotes populares de python fazem isso, incluindo
requests
. Se um pacote usa esta convenção, é fácil habilitar / desabilitar o log para ele, porque o nome do logger será o mesmo nome do pacote (ou será um filho desse logger). Você pode até mesmo registrá-lo no mesmo arquivo que seus outros registradores.logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) requests_logger = logging.getLogger('requests') requests_logger.setLevel(logging.DEBUG) handler = logging.StreamHandler() handler.setLevel(logging.DEBUG) logger.addHandler(handler) requests_logger.addHandler(handler)
fonte
logging.basicConfig(...)
todos os loggers, você terá uma saída paralogging.lastResort
(começando com Python 3.2, que é stderr) se nenhum manipulador foi fornecido ou para o manipulador definido. Portanto, não o use ou você continuará recebendo todas as mensagens de log de qualquer maneira.Não tenho certeza se isso é apropriado para postar, mas eu estava preso por um longo tempo e queria ajudar qualquer pessoa com o mesmo problema, já que não tinha encontrado em nenhum outro lugar!
Eu estava obtendo logs de depuração do matplotlib, apesar de seguir a documentação bastante direta no tutorial de log avançado e solução de problemas . Eu estava iniciando meu logger em
main()
um arquivo e importando uma função para criar um gráfico de outro arquivo (onde importei matplotlib).O que funcionou para mim foi definir o nível de matplotlib antes de importá-lo, ao invés de depois, como eu tinha feito para outros módulos em meu arquivo principal. Isso parecia contra-intuitivo para mim, então se alguém tiver uma ideia de como você pode definir a configuração de um logger que ainda não foi importado, eu ficaria curioso para descobrir como isso funciona. Obrigado!
No meu arquivo principal:
import logging import requests logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) logging.getLogger('requests').setLevel(logging.DEBUG) def main(): ...
Em meu
plot.py
arquivo:import logging logging.getLogger('matplotlib').setLevel(logging.WARNING) import matplotlib.pyplot as plt def generatePlot(): ...
fonte
logger.DEBUG
deveria serlogging.DEBUG
matplotlib
aWARNING
depois que eu importados do módulo, uma vez adicionando-o antes de importar daria um erro fiapos. Ainda funcionou para mim. Estou usandomatplotlib==3.3.2
em Python 3.7 se isso ajudar.Isso desativa todos os registradores existentes, como aqueles criados por módulos importados, enquanto ainda usa o registrador raiz (e sem ter que carregar um arquivo externo).
import logging.config logging.config.dictConfig({ 'version': 1, 'disable_existing_loggers': True, })
Observe que você precisa importar todos os módulos que não deseja que sejam registrados primeiro! Caso contrário, eles não serão considerados como "registradores existentes". Em seguida, desativará todos os registradores desses módulos. Isso pode fazer com que você também perca erros importantes!
Para obter exemplos mais detalhados usando opções relacionadas para configuração, consulte https://gist.github.com/st4lk/6287746 e aqui está um exemplo (parcialmente funcional) usando YAML para configuração com a
coloredlog
biblioteca.fonte
request
exemplo, mas não funcionará quando os módulos importados criarem seus loggers dentro de sua classe que você chamaria mais tarde, como oAPScheduler
faz quando você chamaBackgroundScheduler.BackgroundScheduler()
. Veja aqui uma solução: stackoverflow.com/a/48891485/2441026import logging.config
, não apenas registrar.@Bakuriu explica elegantemente a função. Por outro lado, você pode usar o
getLogger()
método para recuperar e reconfigurar / desativar os registradores indesejados.Eu também queria adicionar o
logging.fileConfig()
método aceita um parâmetro chamadodisable_existing_loggers
que irá desabilitar quaisquer registradores previamente definidos (ou seja, em módulos importados).fonte
Você poderia usar algo como:
logging.getLogger("imported_module").setLevel(logging.WARNING) logging.getLogger("my_own_logger_name").setLevel(logging.DEBUG)
Isso definirá o nível de registro do meu próprio módulo como DEBUG, enquanto evita que o módulo importado use o mesmo nível.
Nota:
"imported_module"
pode ser substituído porimported_module.__name__
(sem aspas), e"my_own_logger_name"
pode ser substituído por__name__
se essa for a maneira que você preferir.fonte
Eu tive o mesmo problema. Eu tenho um arquivo logging_config.py que importo em todos os outros arquivos py. No arquivo logging_config.py, eu defino o nível de registro do logger root como ERROR (por padrão é o aviso):
logging.basicConfig( handlers=[ RotatingFileHandler('logs.log',maxBytes=1000, backupCount=2), logging.StreamHandler(), #print to console ], level=logging.ERROR )
Em outros módulos, eu importo o logging_config.py e declaro um novo registrador e defino seu nível para depuração:
Desta forma, tudo que eu logar em meus arquivos py é registrado, mas o material registrado no nível de depuração e informação por módulos importados como urllib, request, boto3 etc não é registrado. Se houver algum erro nesse módulo de importação, ele será registrado, uma vez que configurei o nível dos loggers de raiz para ERROR.
fonte
Outra coisa a considerar é a propagação propriedade de da classe Logger.
Por exemplo, a biblioteca py-suds para lidar com chamadas de sabão, mesmo colocada em ERROR
logging.getLogger('suds.client').setLevel(logging.ERROR) logging.getLogger('suds.transport').setLevel(logging.ERROR) logging.getLogger('suds.xsdschema').setLevel(logging.ERROR) logging.getLogger('suds.wsdl').setLevel(logging.ERROR)
logs logs sobre um módulo chamado sxbasics.py criaçãog uma grande quantidade de logs
Isso porque a propagação dos logs é True por padrão, configurando como False, em vez disso, recuperei 514 MB de logs.
import logging logging.getLogger("suds").propagate = False logging.getLogger('suds.client').setLevel(logging.ERROR) logging.getLogger('suds.transport').setLevel(logging.ERROR) logging.getLogger('suds.xsdschema').setLevel(logging.ERROR) logging.getLogger('suds.wsdl').setLevel(logging.ERROR)
fonte
Simplesmente fazer algo assim resolve o problema:
logging.config.dictConfig({'disable_existing_loggers': True,})
fonte
No meu caso, a única coisa que ajudou foi forçar um
propagate
atributo de logger indesejado paraFalse
, ou seja,logging.getLogger("module").propagate = False
fonte