Estou usando o logger python. O seguinte é meu código:
import os
import time
import datetime
import logging
class Logger :
def myLogger(self):
logger = logging.getLogger('ProvisioningPython')
logger.setLevel(logging.DEBUG)
now = datetime.datetime.now()
handler=logging.FileHandler('/root/credentials/Logs/ProvisioningPython'+ now.strftime("%Y-%m-%d") +'.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger
O problema que tenho é que obtenho várias entradas no arquivo de log para cada logger.info
chamada. Como posso resolver isso?
Respostas:
O
logging.getLogger()
já é um singleton. ( Documentação )O problema é que toda vez que você chama
myLogger()
, ele está adicionando outro manipulador à instância, o que causa os logs duplicados.Talvez algo assim?
fonte
loggers.update(dict(name=logger))
? não éloggers[name] = logger
mais simples?loggers.update(dict(name=logger))
criará um dicionário com uma única chave chamadaname
e atualizará continuamente essa mesma chave. Estou surpreso que ninguém não tenha mencionado isso antes, pois este código está bastante quebrado :) Fará as alterações necessárias.loggers
dicionário global não é redundante comlogging.getLogger
? já que você realmente deseja apenas evitar adicionar manipuladores extras, parece que você prefere as respostas abaixo que verificam os manipuladores diretamenteDesde o Python 3.2, você pode apenas verificar se os manipuladores já estão presentes e, em caso afirmativo, desmarque-os antes de adicionar novos manipuladores. Isso é muito conveniente durante a depuração e o código inclui a inicialização do registrador
fonte
fez o truque para mim
usando python 2.7
fonte
Já usei o
logger
como Singleton e verifiqueiif not len(logger.handlers)
, mas ainda tenho duplicatas : Era a saída formatada, seguida da não formatada.Solução no meu caso:
logger.propagate = False
Créditos a esta resposta e aos documentos .
fonte
Você está ligando
Logger.myLogger()
mais de uma vez. Armazene a instância do logger que retorna em algum lugar e reutilize- a .Também esteja ciente de que, se você registrar antes de adicionar qualquer manipulador, um padrão
StreamHandler(sys.stderr)
será criado.fonte
Isso é um acréscimo à resposta de @ rm957377, mas com uma explicação de por que isso está acontecendo . Quando você executa uma função lambda no AWS, eles chamam sua função de dentro de uma instância de agrupamento que permanece ativa para várias chamadas. Ou seja, se você chamar
addHandler()
dentro do código de sua função, ele continuará a adicionar manipuladores duplicados ao singleton de registro sempre que a função for executada. O singleton de registro persiste por meio de várias chamadas de sua função lambda.Para resolver isso, você pode limpar seus manipuladores antes de defini-los por meio de:
fonte
.info()
plantão que eu não entendo.Seu logger deve funcionar como singleton. Você não deve criá-lo mais de uma vez. Aqui está um exemplo de como pode ser:
fonte
A implementação do logger já é um singleton.
Fonte - usando o registro em vários módulos
Portanto, a maneira como você deve utilizar isso é -
Vamos supor que criamos e configuramos um logger chamado 'main_logger' no módulo principal (que simplesmente configura o logger, não retorna nada).
Agora em um submódulo, se criarmos um registrador filho seguindo a hierarquia de nomenclatura 'main_logger.sub_module_logger' , não precisamos configurá-lo no submódulo. Apenas a criação do logger seguindo a hierarquia de nomes é suficiente.
E também não adicionará um manipulador duplicado.
Veja esta pergunta para uma resposta um pouco mais detalhada.
fonte
logger = logging.getLogger('my_logger') ; logger.handlers = [logger.handlers[0], ]
A saída do registrador duplo (ou triplo ou ..- com base no número de recarregamentos) também pode ocorrer quando você recarregar seu módulo via
importlib.reload
(pelo mesmo motivo explicado na resposta aceita). Estou adicionando esta resposta apenas para uma referência futura, pois demorei um pouco para descobrir por que minha saída é duplicada (tripla).fonte
Uma solução simples é como
Dessa forma, você evita anexar um novo manipulador à lista subjacente "manipuladores".
fonte
Para a maioria dos casos, quando isso acontece, é necessário chamar logger.getLogger () apenas uma vez por módulo. Se você tem várias aulas como eu, eu poderia chamar assim:
Ambos terão seu próprio nome de pacote completo e método onde registrados.
fonte
Você pode obter uma lista de todos os manipuladores para o logger específico, então você pode fazer algo assim
No exemplo acima, verificamos se o manipulador de um arquivo especificado já está conectado ao logger, mas ter acesso à lista de todos os manipuladores dá a você a capacidade de decidir em quais critérios você deve adicionar outro manipulador ou não.
fonte
Tive esse problema hoje. Como minhas funções eram @staticmethod, as sugestões acima foram resolvidas com random ().
Parecido com:
fonte
fonte