전공영역 공부 기록

python logging모듈 잘못된 설정

악분 2023. 2. 14. 21:49
반응형

문제

아래 예제는 단순히 logging모듈을 이용하여 "hello world"를 출력하는 예제입니다.

예제 코드: https://github.com/sungwook-practice/python_logging_logger.git
# log.py
def getLogger():
    """로거 생성"""
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)

    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    stream_handler = logging.StreamHandler(sys.stdout)
    stream_handler.setFormatter(formatter)
    logger.addHandler(stream_handler)

    return logger

# a.py
def printHelloWorld():
    logger = getLogger()
    logger.debug("hello world")
    
# main.py
if __name__ == "__main__":
    logger = getLogger()
    logger.debug("Start main")
    printHelloWorld()
    logger.debug("[*] End main")

 

실행하면 놀랍게도 "hello world가 두번 실행됩니다.

 

문제원인

문제 원인은 getLogger함수를 호출하여 로거를 생성할 때 마다 handler가 1개씩 추가됩니다. 핸들러는 로깅을 담당하므로 핸들러 갯수만큼 로깅갯수도 증가합니다. 즉 1번 getLogger함수를 호출하면 로깅 1번, 2번 호출하면 로깅 2번이 됩니다.

 

getLogger함수가 호출 될 때, print함수로 handler목록을 출력하여 현재 핸들러를 조회할 수 있습니다.

def getLogger():
    """로거 생성"""
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)

    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    stream_handler = logging.StreamHandler(sys.stdout)
    stream_handler.setFormatter(formatter)
    logger.addHandler(stream_handler)

    print(f"logger.name: {logger.name}, handlers: {logger.handlers}")

    return logger

 

해결방법

해결방법은 여러개 입니다. 쉬운 방법은 로거 생성을 함수로 하지 않고 전역변수로 설정하는 것입니다.

# log.py
import logging
import sys

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)


#a.py
from log import logger

def printHelloWorld():
    logger.debug("hello world")

 

두 번째 방법은 로거를 생성할 때 고유 이름을 설정합니다.

def getLogger(name: str):
  logger = logging.getLogger(name)
  ...

 

세 번째 방법은 이미 handler가 등록되어 있다면 handler등록을 하지 않습니다.

def getLogger(name: str):
  logger = logging.getLogger()
  if logger.handlers:
    return logger
  ...

 

반응형

'전공영역 공부 기록' 카테고리의 다른 글

백준 1062 가르침  (0) 2023.02.19
Argocd kustomize --enable-helm 옵션 활성화  (0) 2023.02.18
python logger설정  (0) 2023.02.14
conatinerd insecure설정  (0) 2023.02.13
백준 17471 게리맨더링  (0) 2023.02.12