[python] Python 로깅 모듈을 사용할 때 중복 로그 출력

파이썬 로거를 사용하고 있습니다. 다음은 내 코드입니다.

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

내가 가진 문제는 각 logger.info호출 에 대해 로그 파일에 여러 항목이 있다는 것 입니다. 어떻게 해결할 수 있습니까?



답변

logging.getLogger()이미 싱글이다. ( 문서 )

문제는를 호출 할 때마다 myLogger()인스턴스에 다른 핸들러를 추가하여 로그가 중복된다는 것입니다.

아마도 이런 건가요?

import os
import time
import datetime
import logging

loggers = {}

def myLogger(name):
    global loggers

    if loggers.get(name):
        return loggers.get(name)
    else:
        logger = logging.getLogger(name)
        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)
        loggers[name] = logger

        return logger


답변

Python 3.2부터는 핸들러가 이미 있는지 확인하고 있다면 새 핸들러를 추가하기 전에 지우면됩니다. 이것은 디버깅 할 때 매우 편리하며 코드에는 로거 초기화가 포함됩니다.

if (logger.hasHandlers()):
    logger.handlers.clear()

logger.addHandler(handler)


답변

import datetime
import logging
class Logger :
    def myLogger(self):
       logger=logging.getLogger('ProvisioningPython')
       if not len(logger.handlers):
          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

나를 위해 속임수를 만들었다

파이썬 2.7 사용


답변

난 이미 사용 loggerA와 싱글 및 확인 if not len(logger.handlers),하지만 여전히 중복을 가지고 : 그것은는 포맷 된 출력했다 포맷되지 않은 하였다.

제 경우에는 해결책 :
logger.propagate = False

이 답변문서에 대한 크레딧 .


답변

Logger.myLogger()두 번 이상 전화 하고 있습니다. 반환하는 로거 인스턴스를 어딘가에 저장하고 다시 사용 합니다 .

또한 핸들러를 추가하기 전에 로그인하면 기본값 StreamHandler(sys.stderr)이 생성됩니다.


답변

이것은 @ rm957377의 답변에 추가 되었지만 왜 이런 일이 발생하는지에 대한 설명이 있습니다. AWS에서 람다 함수를 실행하면 여러 호출에 대해 살아있는 래핑 인스턴스 내에서 함수를 호출합니다. 즉, addHandler()함수 코드 내에서 호출 하면 함수가 실행될 때마다 로깅 싱글 톤에 중복 처리기가 계속 추가됩니다. 로깅 싱글 톤은 람다 함수의 여러 호출을 통해 유지됩니다.

이를 해결하기 위해 다음을 통해 설정하기 전에 핸들러를 지울 수 있습니다.

logging.getLogger().handlers.clear()
logging.getLogger().addHandler(...)


답변

로거는 싱글 톤으로 작동해야합니다. 두 번 이상 생성하면 안됩니다. 다음은 어떻게 보이는지 예입니다.

import os
import time
import datetime
import logging
class Logger :
    logger = None
    def myLogger(self):
        if None == self.logger:
            self.logger=logging.getLogger('ProvisioningPython')
            self.logger.setLevel(logging.DEBUG)
            now = datetime.datetime.now()
            handler=logging.FileHandler('ProvisioningPython'+ now.strftime("%Y-%m-%d") +'.log')
            formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
            handler.setFormatter(formatter)
            self.logger.addHandler(handler)
        return self.logger

s = Logger()
m = s.myLogger()
m2 = s.myLogger()
m.info("Info1")
m2.info("info2")