Estou usando o log Python e, por algum motivo, todas as minhas mensagens estão aparecendo duas vezes.
Eu tenho um módulo para configurar o registro:
# BUG: It's outputting logging messages twice - not sure why - it's not the propagate setting.
def configure_logging(self, logging_file):
self.logger = logging.getLogger("my_logger")
self.logger.setLevel(logging.DEBUG)
self.logger.propagate = 0
# Format for our loglines
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
# Setup console logging
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(formatter)
self.logger.addHandler(ch)
# Setup file logging as well
fh = logging.FileHandler(LOG_FILENAME)
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
self.logger.addHandler(fh)
Mais tarde, chamo este método para configurar o registro:
if __name__ == '__main__':
tom = Boy()
tom.configure_logging(LOG_FILENAME)
tom.buy_ham()
E então, digamos, o módulo buy_ham, eu chamaria:
self.logger.info('Successfully able to write to %s' % path)
E por algum motivo, todas as mensagens estão aparecendo duas vezes. Comentei um dos manipuladores de fluxo, ainda é a mesma coisa. Um pouco estranho, não sei por que isso está acontecendo ... lol. Supondo que eu tenha esquecido algo óbvio.
Saúde, Victor
configure_logging()
não é chamado duas vezes (por exemplo, do construtor também)? Apenas uma instância de Boy () foi criada?self.logger.handlers = [ch]
vez disso, resolveria esse problema, embora seja melhor apenas garantir que você não execute este código duas vezes, por exemplo, usandoif not self.logger
no início.Respostas:
Você está chamando
configure_logging
duas vezes (talvez no__init__
método deBoy
):getLogger
retornará o mesmo objeto, masaddHandler
não verifica se um manipulador semelhante já foi adicionado ao logger.Tente rastrear chamadas para esse método e eliminar um deles. Ou configure um sinalizador
logging_initialized
inicializado comFalse
no__init__
método deBoy
e mudeconfigure_logging
para não fazer nada selogging_initialized
forTrue
, e configure-o paraTrue
depois de inicializar o registrador.Se o seu programa criar várias
Boy
instâncias, você terá que mudar a maneira como faz as coisas com umaconfigure_logging
função global adicionando os manipuladores e oBoy.configure_logging
método apenas inicializando oself.logger
atributo.Outra maneira de resolver isso é verificar o atributo handlers do seu logger:
fonte
logger
variável utilizada, não foi a instanciada de uma das minhas classes, mas alogger
variável presente no cache do Python3 , e o manipulador foi adicionado a cada 60 segundos por um AppScheduler que eu configurei. Então, essaif not logger.handlers
é uma maneira muito inteligente de evitar esse tipo de fenômeno. Obrigado pela solução, camarada :)!Se você está vendo este problema e não está adicionando o manipulador duas vezes, veja a resposta de abarnert aqui
Dos documentos :
Portanto, se você deseja um manipulador personalizado em "teste" e não quer que suas mensagens também vão para o manipulador raiz, a resposta é simples: desative seu sinalizador de propagação:
logger.propagate = False
fonte
O manipulador é adicionado cada vez que você liga de fora. Tente remover o manipulador depois de terminar seu trabalho:
fonte
logger.handlers.pop()
em python 2.7, faz o truqueEu sou um novato em Python, mas isso pareceu funcionar para mim (Python 2.7)
fonte
No meu caso, devo definir
logger.propagate = False
para evitar impressão dupla.No código abaixo, se você remover
logger.propagate = False
, verá uma impressão dupla.fonte
logger.propagate = False
foi a solução para evitar o registro duplo em um aplicativo Flask hospedado por Waitress, ao fazer login naapp.logger
instância do Flask .Uma chamada para
logging.debug()
chamadaslogging.basicConfig()
se não houver manipuladores raiz instalados. Isso estava acontecendo comigo em uma estrutura de teste onde eu não conseguia controlar a ordem de disparo dos casos de teste. Meu código de inicialização estava instalando o segundo. O padrão usa o log.BASIC_FORMAT que eu não queria.fonte
Parece que se você enviar algo para o logger (acidentalmente) e depois configurá-lo, é tarde demais. Por exemplo, em meu código eu tinha
Eu obteria algo como (ignorando as opções de formato)
e tudo foi escrito para stdout duas vezes. Acredito que isso seja porque a primeira chamada para
logging.warning
cria um novo manipulador automaticamente e, em seguida, adicionei explicitamente outro manipulador. O problema foi embora quando removi a primeiralogging.warning
chamada acidental .fonte
Eu estava tendo uma situação estranha onde os logs do console foram duplicados, mas os logs dos meus arquivos não. Depois de uma tonelada de escavações, descobri.
Esteja ciente de que pacotes de terceiros podem registrar loggers. Isso é algo que deve ser observado (e em alguns casos não pode ser evitado). Em muitos casos, o código de terceiros verifica se há algum gerenciador de log de raiz existente ; e se não houver - eles registram um novo manipulador de console.
Minha solução para isso foi registrar meu logger de console no nível raiz:
fonte