목차
logging
파이썬 표준 라이브러리인 logging은 애플리케이션에서 발생하는 이벤트를 로깅하는 데 유용한 모듈을 제공한다.
log는 오류의 원인을 찾는데 가장 많이 사용한다.
기본적으로 파이썬과 logging 모듈은 오류의 원인을 알려주는 다양한 log를 제공하지만 프로그래머에게 유용할 수 있는 자체 로그를 만드는 것이 좋다.
자체 로그를 사용하는 예로는 모든 인터넷 시스템을 예시로 들 수 있다.
사용자가 사이트를 방문할 때 사용하는 브라우저에 대한 정보를 기록할 수 있다.
문제가 발생하면 어떤 브라우저에서 문제가 발생했는지 파악할 수 있다.
파이썬에서는 로그를 다양한 위치에 저장할 수 있다.
대부분 파일 형식이지만, 출력 스트림이나 외부 서비스 형식일 수도 있다.

1. logging 가져오기
import logging
2. logger 객체 만들기
하나의 어플리케이션에는 개발자와 모듈 프로그래머가 직접 생성한 여러개의 로거(logger)가 있을 수 있다.
getLogger() 인자에 이름을 지정하지 않고 간단하게 루트 로거를 사용할 수 있다.
루트 로거는 계층 구조에서 가장 높은 위치에 있고, 계층 구조에서 위치는 함수에 전달된 이름에 따라 결정된다.
dot(.)을 통해 트리구조를 이루도록 설계할 수 있다.
import logging
root_logger = logging.getLogger()
mother_logger = logging.getLogger('mother')
son_logger = logging.getLogger('mother.son')
recommend_logger = logging.getLogger(__name__)
아래의 recommend_logger와 같은 형태를 권장한다.
이렇게 하면 로깅된 메세지의 출처를 쉽게 지정할 수 있다.
__name__은 해당 모듈의 실제 이름을 의미하고
logging.getLogger(__name__)는 현재 모듈의 이름을 기반으로 로거 인스턴스를 가져온다.
파이썬의 logging 모듈에서 가장 권장되는 로거 생성 방식이다.
참고로 같은 이름으로 함수를 여러번 호출하면 항상 동일한 객체가 반환된다.
3. logging levels
logging 객체를 활용하여 서로 다른 로깅 수준(logging level)을 가진 로그를 생성할 수 있고,
이를 통해 덜 중요한 로그와 심각한 오류를 보고 로그를 구분할 수 있다.
기본적으로 다음과 같은 로깅 레벨이 정의되어 있다.
| level name | value |
| CRITICAL | 50 |
| ERROR | 40 |
| WARNING | 30 |
| INFO | 20 |
| DEBUG | 10 |
| NOTSET | 0 |
각 레벨은 이름과 숫자값이 존재한다.
직접 레벨을 정의할 수 있지만 logging 모듈에서 제공하는 레벨로도 충분하다.
logging 객체에는 로깅 레벨을 설정하는 메서드가 있다.
import logging
logger = logging.getLogger()
logger.critical('critical')
logger.error('error')
logger.warning('warning')
logger.info('info')
logger.debug('debug')
CRITICAL:root:critical
ERROR:root:error
WARNING:root:warning
info 와 debug가 출력되지 않은 것을 알 수 있다.
이는 기본 설정과 관련이 있다.
아래의 글을 참고하자.
4.setLevel 메서드
루트 로거의 로깅 수준이 WARNING으로 설정되어 있다. 그렇기 때문에 위의 예제와 같이 info , debug는 출력되지 않는다.

위의 표와 같이 해당하는 로깅 수준이상의 위험도를 표시하게 된다.
setLevel 메서드를 통해 변경해보도록 하자.
import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.critical('critical')
logger.error('error')
logger.warning('warning')
logger.info('info')
logger.debug('debug')
CRITICAL:root:critical
ERROR:root:error
WARNING:root:warning
INFO:root:info
DEBUG:root:debug
logging.DEBUG를 설정하므로 debug 이상의 레벨 수준은 전부 출력되는 것을 볼 수 있다.
5. logger level 설정 유의사항
logging.getLogger('some_name')과 같이 이름을 지정하여 로거를 생성하면, 해당 로거의 기본 레벨은 NOTSET으로 설정된다.
이 NOTSET 레벨은 "레벨이 명시적으로 설정되지 않았다"는 의미이며,
실제로 메시지를 처리할 레벨은 로거 계층 구조(Logger Hierarchy)를 따라 결정된다.
레벨 결정 규칙:
-
상위 로거 따라가기
로거의 레벨이 NOTSET인 경우, 이 로거는 메시지를 처리할 때 가장 가까운 상위(부모) 로거의 레벨 설정을 따라간다. - NOTSET 부모 체인
만약 가장 가까운 부모 로거의 레벨도 NOTSET으로 설정되어 있다면,
그 부모는 다시 그 자신의 부모 로거의 레벨 설정을 따르게 된다.
이 과정은 로거 계층 구조를 거슬러 올라가면서 NOTSET이 아닌 레벨을 가진 첫 번째 로거를 찾을 때까지 계속된다. - 루트 로거까지 NOTSET인 경우 (모든 메시지 처리)
만약 로거 계층 구조의 최상위인 루트 로거(Root Logger)까지 모든 상위 로거의 레벨이 NOTSET으로 설정되어 있다면(참고: 일반적으로 루트 로거의 기본 레벨은WARNING이므로, 이 상황은 개발자가 명시적으로 루트 로거를 NOTSET으로 변경하지 않는 한 발생하기 어렵다.)
(매우 드문 경우로), 모든 메시지는 레벨에 관계없이 처리된다.
6. 기본 logger level 설정
기본 로깅 구성은 basicConfig 메서드를 호출하여 구성할 수 있다.
basicConfig() 메서드를 인수를 지정하지 않고 메서드를 사용할 경우
StreamHandler 라는 로그를 처리하여 콘솔에 표시하는 객체가 생성된다.
import logging
logging.basicConfig(level=logging.CRITICAL, filename="log_test.log", filemode='a')
logger = logging.getLogger()
logger.critical('critical message')
logger.error('error message')
logger.warning('warning message')
logger.info('info message')
logger.debug('debug message')
colab으로는 테스트가 불가하나(파일 생성이 안됨.)
로컬에서는 filename에 해당하는 파일이 생성되고,
코드를 실행할 때 마다 CRITICAL:root:critical 문구가 추가되는 것을 확인할 수 있다.
모드가 a로 설정되어있기 때문인데, 이는 open 함수에서 사용하는 것과 유사한 모드를 사용할 수 있다.
참고로 basicConfig 방법은 루트 로거와 자체 핸들러가 정의되지 않은 자식 로거의 구성을 변경한다.
- format
import logging
FORMAT = "%(name)s : %(asctime)s: %(levelname)s: %(message)s"
logging.basicConfig(level=logging.CRITICAL, filename="log_test.log", filemode='a', format=FORMAT)
logger = logging.getLogger()
logger.critical('critical message')
logger.error('error message')
logger.warning('warning message')
logger.info('info message')
logger.debug('debug message')
format 인수는 기본의 로그 출력 형식을 변경하는 데 사용할 수 있다.
인수는 문자나 LogRecod의 속성을 사용하여 정의할 수 있다.
%(name)s : %(asctime)s: %(levelname)s: %(message)s
root: 2025-07-17 -9:56:43,225 : CRITICAL : critical message
LogRecord 객체의 속성을 결합하여 생성하고 있는데 LogRecord 객체는 logger에 의해 자동으로 생성된다.
사용 가능한 속성 전체 목록은 아래의 링크를 통해 확인할 수 있다.
https://docs.python.org/3/library/logging.html#logrecord-attributes
logging — Logging facility for Python
Source code: Lib/logging/__init__.py Important: This page contains the API reference information. For tutorial information and discussion of more advanced topics, see Basic Tutorial, Advanced Tutor...
docs.python.org
| attributes | means |
| %(name)s | 로깅 메서드를 호출하는 로거의 이름으로 대체됨. 현재의 경우 root logger |
| %(asctime)s | 객체 생성 시간을 사람이 읽을 수 있는 형태의 날짜 형식으로 대체됨. 뒤의 숫자는 밀리초단위를 표현한다. |
| %(levelname)s | 설정된 로그 레벨로 대체됨. 현재의 경우 CRITICAL |
| %(message)s | 정의된 메세지를 출력한다. |
7. 핸들러를 이용한 파일 저장
import logging
logger = logging.getLogger(__name__)
handler = logging.FileHandler('prod.log', mode='a')
handler.setLevel(logging.CRITICAL)
logger.addHandler(handler)
logger.critical('critical message')
logger.error('error message')
logger.warning('warning message')
logger.info('info message')
logger.debug('debug message')
각 logger는 다양한 위치와 형식으로 저장할 수 있다.
대부분의 경우 로그를 파일에 저장하는 것이 좋다.
- logging 모듈에는 FileHandler라는 클래스가 있는데, FileHandler 객체를 생성할 때 로그가 저장될 파일 이름을 인수로 전달해야 한다.
- 핸들러에서 처리한 로깅 레벨을 설정해야한다. 기본적으로 새로이 생성된 핸들러는 NOTSET으로 설정된다.
- addHandler() 메서드를 통해 logger에 추가한다.
각 로거에는 여러 개의 핸들러를 추가할 수 있다.
한 핸들러는 로그를 파일에 저장하고, 다른 핸들러는 외부 서비스로 전송할 수 있다.
로거의 기본값의 WARMING 보다 낮은 레벨의 메세지를 전달하기 위해서는 레벨 임계값을 설정해야한다.
8. Formatter 활용한 포멧 변경
import logging
FORMAT = "%(name)s : %(asctime)s: %(levelname)s: %(message)s"
logger = logging.getLogger(__name__)
handler = logging.FileHandler('prod.log', mode='a') # handler
handler.setLevel(logging.CRITICAL) # handler <- level config
formatter = logging.Formatter(FORMAT) # formatter
handler.setFormatter(formatter) # handler <- formatter
logger.addHandler(handler) # logger <- handler
logger.critical('critical message')
logger.error('error message')
logger.warning('warning message')
logger.info('info message')
logger.debug('debug message')
- logger 모듈의 Formatter 클래스의 객체를 생성하는데,
이전에 format을 인수로 활용한 것과 같은 형식으로 string 의 형태로 넣어준다. - 생성한 핸들러 객체에 setFormatter()메서드를 통해 포매터를 설정한다.
- 이후 정의한 포멧과, 핸들러에 정의된 로깅 레벨에 맞게 파일이 생성되고 이후 추가되는 것을 확인할 수 있다.
'Development > Python' 카테고리의 다른 글
| [python] GUI programming tkInter (소개 및 생성) (6) | 2025.08.19 |
|---|---|
| [python] configparser 모듈 (2) | 2025.07.18 |
| [python] CSV, CSV 모듈 (0) | 2025.07.16 |
| [python] XML , XML 문서의 CRUD (0) | 2025.07.15 |
| [python] SQLite, sqlite3을 활용한 CRUD (1) | 2025.07.14 |