[Python3] logging 모듈을 이용하여 로그파일 생성하기

2019. 7. 9. 16:00Python/Basic

300x250
반응형

Python에서 로깅을 설정해볼까요.

  1. 로깅 포맷을 설정하기
  2. 다음날이 되었을 시, 기존 파일의 suffix에 날짜 정보를 붙여 로그파일 구분
  3. 로그 폴더가 없을 시 폴더 생성

01

python 앱 내의 py_sched 모듈에 logger.py 를 생성하여 로깅 설정을 해서 다른 파일들에서 로깅을 이용할 수 있도록 할 예정입니다.


※ 참고로 로깅 단계는
NOTSET - DEBUG - INFO - WARNING - ERROR - CRITICAL 순입니다.
update 관련 로그는 INFO
에러 발생시 로그는 CRITICAL
일반 메시지는 DEBUG 로 설정하면 좋겠네요.


import logging


logger = logging.getLogger(__name__)
formatter = logging.Formatter(u'%(asctime)s [%(levelname)8s] %(message)s')
logger.setLevel(logging.DEBUG)

로그 출력 형태를 logging.Formatter로 설정할 수가 있는데, 저는 간단하게 시간, 로그레벨, 로그메시지로만 구성했습니다.
로그 출력 형태를 더 세세하게 하고 싶은 사람들은 문서를 참고해 주세요.



from logging.handlers import TimedRotatingFileHandler

...

fileHandler = TimedRotatingFileHandler(filename='./logs/py_sched.log', when='midnight', interval=1, encoding='utf-8')
fileHandler.setFormatter(formatter)
fileHandler.suffix = '%Y%m%d'
fileHandler.setLevel(logging.ERROR)
logger.addHandler(fileHandler)

streamHandler = logging.StreamHandler()
streamHandler.setFormatter(formatter)
streamHandler.setLevel(logging.DEBUG)
logger.addHandler(streamHandler)

로그를 콘솔 출력 이외에 파일로도 출력하기 위해 fileHandler와 streamHandler을 추가하였습니다.

특히 파일로그는 자정이 되면 새로운 파일을 생성하도록 하기 위해 TimedRotatingFileHandler를 이용했습니다.
(기존의 'py_sched.log' 로그파일을 py_sched.log.20190709 와 같은 이름으로 변경하고 새로운 로그파일을 생성하도록 설정합니다.)

핸들러별로 로그 레벨을 변경하고 싶다면 위와 같이 각 핸들러별로 레벨을 설정해주면 됩니다.



import os

...

log_dir = './logs'

if not os.path.exists(log_dir):
    os.mkdir(log_dir)

fileHandler = TimedRotatingFileHandler(filename=log_dir + '/py_sched.log', when='midnight', interval=1, encoding='utf-8')

참고로, 로그파일이 위치한 logs 폴더가 존재하지 않을 시, 에러가 발생됩니다.
이를 방지하기 위해 fileHandler 초기화 이전에 폴더의 유무를 체크하여 없을 경우 생성하는 것이 좋습니다.



def requests_error_handler(id, exception):
    from py_sched.logger import logger
    from py_sched.services import update_scheduling_status

    exception_name = type(exception).__name__

    logger.debug('  {}'.format(exception_name))

    if exception_name == 'ConnectionError':
        status = 'C'
    elif 'Timeout' in exception_name:
        status = 'T'
    else:
        status = 'E'
    cnt = update_scheduling_status(id, status)
    if cnt > 0:
        logger.critical('  {}로 인하여 id {}의 status를 {}로 업데이트'.format(exception_name, id, status))
    else:
        logger.error('  id {}의 status를 {}로 업데이트 실패'.format(id, status))

위에서 우리가 정의한 logger 파일을 import하여 사용하면 됩니다.
info, debug, critical, error 등의 레벨로 출력할 수 있습니다.

2019-07-09 15:44:54,093 [   DEBUG]   ConnectionError
2019-07-09 15:44:56,164 [CRITICAL]   ConnectionError로 인하여 id 3의 status를 C로 업데이트

로그 출력 화면입니다.

300x250
반응형