logging 모듈은 로그를 기록하기 위한 파이썬의 표준 도구입니다. 이는 로거의 계층 구조를 구현하고 로깅 수준(심각도 수준)을 지원합니다: DEBUG, INFO, WARNING, ERROR, CRITICAL. 올바른 사용은 출력을 중앙 집중식으로 관리하고, 로그를 파일에 저장하고, 이메일로 전송하고, 수준에 따라 필터링하는 등의 작업을 가능하게 합니다.
주요 아이디어는 각 모듈에서 이름이 있는 로거를 생성하는 것입니다 (logging.getLogger(__name__)). 전역 root 로거를 매번 만들지 않습니다. 구성(형식, 핸들러, 수준)은 애플리케이션 시작 시 중앙 집중식으로 이루어집니다.
설정 예시:
import logging logging.basicConfig(format='%(levelname)s:%(name)s:%(message)s', level=logging.INFO) logger = logging.getLogger(__name__) def foo(): logger.info('정보 메시지') logger.error('오류!') foo()
각 모듈에서 logging.basicConfig()를 호출하면 왜 안됩니까? 이렇게 하면 무슨 일이 발생합니까?
답변: logging.basicConfig()는 Python 세션 동안 root 로거를 단 한 번만 설정합니다. 이미 root 로거가 초기화된 경우 반복 호출은 무시됩니다. 따라서 서로 다른 모듈이 자체 형식/수준으로 basicConfig()를 호출하려고 하면 최초의 하나만 작동합니다!
이야기
대규모 프로젝트에서 각 개발자가 basicConfig와 로컬 핸들러를 통해 로깅을 개인의 취향에 맞게 설정했습니다. 그 결과 일부 로그는 전혀 출력되지 않았고, 다른 로그는 10배 중복되었으며, 서로 다른 모듈의 메시지가 하나의 파일에 담기지 않았습니다.
이야기
웹 서비스의 다단계 로깅으로 이전하는 과정에서 getLogger(__name__)를 통해 로거 이름을 지정하는 것을 잊고, 모든 곳에서 root 로거에 기록했습니다. 그 결과 특정 로그가 어디에서 왔는지 파악할 수 없었습니다.
이야기
모든 메시지를 기록하기 위해 logger.error() 함수를 사용했습니다. 따라서 자동 모니터링 시스템이 높은 오류 수준을 감지하고 빈번히 "경고"를 발생시켰습니다. 왜냐하면 이들은 단순히 debug/정보 메시지였기 때문입니다.