Logo

파이썬 기본 로깅 - logging 내장 모듈

logging 내장 모듈

외부 라이브러리가 없더라도 대부분의 애플리케이션에서는 파이썬에 내장되어 있는 logging 모듈만으로도 충분히 로깅이 가능합니다. logging 내장 모듈은 파이썬만 설치되어 있다면 다음과 같이 인터프리터에서도 간단히 임포트해서 사용해볼 수 있습니다.

>>> import logging
>>> logging.warning('경고!')
WARNING:root:경고!

심각도 별 로깅

logging 모듈은 5단계의 심각도 따라 다른 메서드를 제공하고 있습니다. 기본적으로 이 중 하나의 메서드에 로깅할 메시지를 인자로 넘겨서 호출하면 로그가 남습니다.

import logging


def main():
    logging.debug("디버그")
    logging.info("정보")
    logging.warning("경고")
    logging.error("오류")
    logging.critical("심각")


if __name__ == "__main__":
    main()

위 프로그램을 실행해보면 다음과 같이 debuginfo를 제외하고 로그가 출력되는 것을 알 수 있습니다. 이는 추가 설정을 하지 않으면 기본 로깅 레벨인 warning 이상의 심각도에 대해서만 로그가 남기 때문입니다.

WARNING:root:경고
ERROR:root:오류
CRITICAL:root:심각

로깅 레벨 변경

basicConfig() 메서드를 사용하면 간단하게 로깅 레벨을 바꿔줄 수 있습니다. 다음과 같이 로깅 레벨을 DEBUG로 낮춰주면 모든 로그가 출력될 것입니다.

import logging

logging.basicConfig(level=logging.DEBUG)


def main():
    logging.debug("디버그")
    logging.info("정보")
    logging.warning("경고")
    logging.error("오류")
    logging.critical("심각")


if __name__ == "__main__":
    main()
DEBUG:root:디버그
INFO:root:정보
WARNING:root:경고
ERROR:root:오류
CRITICAL:root:심각

로깅 포맷 변경

콘솔에 출력된 로그를 보면 인자로 넘긴 메시지 외에도 그 앞에 추가적인 정보(로깅 레벨, 로거 이름)가 포함되어 있는 것을 알 수 있습니다. 이는 기본 로깅 포맷이 %(levelname)s:%(name)s:%(message)s이기 때문이며, 로깅 포맷도 basicConfig() 메서드를 이용해서 쉽게 변경이 가능합니다.

import logging

logging.basicConfig(level=logging.DEBUG, format="'%(asctime)s - %(message)s'")


def main():
    logging.debug("디버그")
    logging.info("정보")
    logging.warning("경고")
    logging.error("오류")
    logging.critical("심각")


if __name__ == "__main__":
    main()
'2020-02-02 15:48:17,420 - 디버그'
'2020-02-02 15:48:17,420 - 정보'
'2020-02-02 15:48:17,420 - 경고'
'2020-02-02 15:48:17,421 - 오류'
'2020-02-02 15:48:17,421 - 심각'

이 밖에 자세한 로깅 포맷 문법에 대해서는 공식 레퍼런스를 참고바랍니다.

예외 로깅

예외가 발생한 경우에는 exception()를 사용하여 로그 메시지 뿐만 아니라 스택 트레이스에 대한 로그까지 남길 수 있습니다.

import logging


def calc():
    1 / 0


def main():
    try:
        calc()
    except Exception:
        logging.exception("예외")


if __name__ == "__main__":
    main()
ERROR:root:예외
Traceback (most recent call last):
  File "learn_logging.py", line 10, in main
    calc()
  File "learn_logging.py", line 5, in calc
    1 / 0
ZeroDivisionError: division by zero

유동적 로깅 레벨

좀 더 범용적인 메서드인 log()를 사용하면, 좀 더 유용적으로 심각도 레벨을 지정할 수 있습니다. log() 메서드에 로깅 레벨을 인자로 넘길 수 있기 때문에, 다음과 같이 로깅 레벨을 런타임에 바꿀 수 있습니다.

import logging


def main():
    level = logging.ERROR
    logging.log(level, "메시지")

    level = logging.WARNING
    logging.log(level, "메시지")


if __name__ == "__main__":
    main()
ERROR:root:메시지
WARNING:root:메시지

마치면서

지금까지 파이썬의 logging 내장 모듈을 사용하여 정말 기본적인 로깅 방법에 대해서 살펴보았습니다. 간단한 애플리케이션에서는 이와 같이 최상위 로거만 사용해도 크게 부족함이 없지만, 여러 개의 모듈로 이루어진 복잡한 애플리케이션에서는 모듈 단위로 계층적인 로깅을 고려해봐야 합니다. 이 부분에 대해서는 추후 포스팅를 통해 다루도록 하겠습니다.