레이블이 logger인 게시물을 표시합니다. 모든 게시물 표시
레이블이 logger인 게시물을 표시합니다. 모든 게시물 표시

2021년 10월 8일 금요일

python 멀티 로그 레벨을 가지는 로거(how to set multi setlevel in python logger)

python logger를 사용하면서 우리는 가끔 파일로 출력되는 레벨과 화면으로 출력되는 레벨을 다르게 하고 싶은 경우가 있습니다.

여기에서는 핸들러별 level을 설정하는 방법에 대해서 알아보겠습니다.

기본적으로 handler 별로 설정하는건 간단합나다만, 동작중에 값을 변경시키고 기존 library에 값을 변경하는 예제를 만들어보았습니다.


예제 아래는 기존에 사용하던 color 출력기능을 가진 예제입니다. 여기에 레벨을 변경하는 기능을 가지도록 수정하였습니다.

import datetime
import sys
import os
import time
import logging
import colorlog
from logging import FileHandler
from logging import handlers

class CustomLog:
	def __init__(self):
		self.rotatingHandler = None
		self.fileHandler = None
		self.streamHandler = None
		pass
		
	def create(self,logfolder='', app_name=__name__, logprefix='log_', NEED_BACKUP_FILE = True, NEED_SCREEN_AND_FILE = True, level=logging.DEBUG, format='[%(asctime)s] %(levelname)s [%(filename)s.%(funcName)s:%(lineno)d] %(message)s', maxBytes=10*1024*1024, backupCount = 10, encoding='utf-8', color=True):
		LOG_PREFIX = logprefix
		LOG_FOLDER_NAME = logfolder
		# 로그 파일 핸들러
		now = datetime.datetime.now().isoformat()[:10]
		logf = LOG_PREFIX + now + ".log"
		if LOG_FOLDER_NAME!='' and not os.path.exists(LOG_FOLDER_NAME):
			os.makedirs(LOG_FOLDER_NAME)
		logf = os.path.join(LOG_FOLDER_NAME, logf)
		logger = self.getLogger(logf, app_name, NEED_BACKUP_FILE, NEED_SCREEN_AND_FILE, level, format, maxBytes, backupCount, encoding, color)
		logger.logfilename_ = logf
		return logger

	def getLogger(self, filename, app_name, NEED_BACKUP_FILE, NEED_SCREEN_AND_FILE, level, format, maxBytes, backupCount, encoding, color):
		if color :
			self.logger = colorlog.getLogger(app_name)
		else:
			self.logger = logging.getLogger(app_name)
		
		self.logger.handlers.clear()
		self.logger.propagate = False
		# log level은 아래 순서에 따른다. setLevel 과 같거나 큰 출력만 나오게 된다.
		# logger.setLevel(logging.CRITICAL) 인 경우 logger.critical() 만 나온다
		#
		# logger.debug("debug")
		# logger.info("info")
		# logger.warning("warning")
		# logger.error("error")
		# logger.critical("critical")
		self.logger.setLevel(level)

		# 포맷을 결정한다. 좀더 자세한 정보는 다음 링크를 참조한다
		# https://docs.python.org/3/library/logging.html#logrecord-attributes
		if color :
			logFormatter = colorlog.ColoredFormatter('%(log_color)s'+format)
		else :
			logFormatter = logging.Formatter(format)
		
		if NEED_BACKUP_FILE == True:
			self.rotatingHandler = handlers.RotatingFileHandler(filename=filename, maxBytes=maxBytes, backupCount = backupCount, encoding=encoding)
			self.rotatingHandler.setFormatter(logFormatter)
			self.logger.addHandler(self.rotatingHandler)
		else:
			self.fileHandler = logging.FileHandler(filename)
			self.fileHandler.setFormatter(logFormatter)
			self.logger.addHandler(self.fileHandler)

		# StreamHandler 는 self.logger.critical("critical") 이런 형태의 로그가 화면으로도 나오고 file로도 저장이 되도록 한다
		if NEED_SCREEN_AND_FILE == True:
			self.streamHandler = logging.StreamHandler()
			self.streamHandler.setFormatter(logFormatter)
			self.logger.addHandler(self.streamHandler)
		return self.logger
	def setLevel(self,filelevel,streamlevel):
		if self.rotatingHandler :
			self.rotatingHandler.setLevel(filelevel)
		if self.fileHandler :
			self.fileHandler.setLevel(filelevel)
		if self.streamHandler :
			self.streamHandler.setLevel(streamlevel)
		
	
	
if __name__ == "__main__":
	LOG = CustomLog()
	logger = LOG.create('log')
	print("test")
	logger.debug("debug test")
	logger.info("info test")
	logger.warning("warning test")
	logger.error("error test")
	logger.critical("critical test")
	LOG.setLevel(filelevel=logging.INFO,streamlevel=logging.ERROR)
	logger.debug("debug test")
	logger.info("info test")
	logger.warning("warning test")
	logger.error("error test")
	logger.critical("critical test")

main 쪽을 보면 아래와 같은 부분이 있습니다.

파일은 INFO 이상 stream(화면 출력은) ERROR 이상이 나오도록 설정하는 코드 입니다.

LOG.setLevel(filelevel=logging.INFO,streamlevel=logging.ERROR)

코드를 따라가보면 저장된 핸들러들에 각각 setLevel 하는 부분이 보입니다.

위와 같이 하면 콘솔에서는 아래와 같이 출력됩니다.

[2021-10-07 20:38:50,724] DEBUG [_23_logger_multi_level.py.<module>:84] debug test
[2021-10-07 20:38:50,725] INFO [_23_logger_multi_level.py.<module>:85] info test
[2021-10-07 20:38:50,726] WARNING [_23_logger_multi_level.py.<module>:86] warning test
[2021-10-07 20:38:50,728] ERROR [_23_logger_multi_level.py.<module>:87] error test
[2021-10-07 20:38:50,729] CRITICAL [_23_logger_multi_level.py.<module>:88] critical test
[2021-10-07 20:38:50,730] ERROR [_23_logger_multi_level.py.<module>:93] error test
[2021-10-07 20:38:50,731] CRITICAL [_23_logger_multi_level.py.<module>:94] critical test

자세히 보시면 똑같이 두벌 출력이 되어야하는데 두번째 debug test, info test, warning test 가 출력이 되지 않았습니다. streamlevel은 ERROR로 설정했기 때문입니다.

이때 저장된 파일을 보면 아래와 같습니다.

[2021-10-07 20:38:50,724] DEBUG [_23_logger_multi_level.py.<module>:84] debug test
[2021-10-07 20:38:50,725] INFO [_23_logger_multi_level.py.<module>:85] info test
[2021-10-07 20:38:50,726] WARNING [_23_logger_multi_level.py.<module>:86] warning test
[2021-10-07 20:38:50,728] ERROR [_23_logger_multi_level.py.<module>:87] error test
[2021-10-07 20:38:50,729] CRITICAL [_23_logger_multi_level.py.<module>:88] critical test
[2021-10-07 20:38:50,730] INFO [_23_logger_multi_level.py.<module>:91] info test
[2021-10-07 20:38:50,730] WARNING [_23_logger_multi_level.py.<module>:92] warning test
[2021-10-07 20:38:50,730] ERROR [_23_logger_multi_level.py.<module>:93] error test
[2021-10-07 20:38:50,731] CRITICAL [_23_logger_multi_level.py.<module>:94] critical test

filelevel=logging.INFO 영향으로 debug test 만 한번 출력되었습니다. 


참고할만한 링크

2021년 10월 3일 일요일

python logger,colored log (컬러 로거 logger)


python logger는 디버깅하는데 기본적인 도구 입니다.

이번에 레벨에 따른 색상을 지원하는 colorlog를 이용하여 기존의 logger를 변경하였습니다.

이 logger 의 특징

파일 저장과 스트림 출력을 동시에 하고 있으며 파일 저장은 파일 갯수와 용량을 이용한 Rotating파일 핸들러도 동시에 동작하고 있습니다.

로그 폴더를 기본으로 정하고 로그 폴더가 없으면 자동을 생성됩니다.

self.logger.handlers.clear() 를 추가함으로서 logger가 생성될때마다 중복 핸들러가 생성되는것을 방지합니다. 이 부분이 없으면 생성될때마다 로그가 여러번 출력되게 됩니다.

예제

여러 파일에서 로거를 어떻게 사용하는지 예제가 있습니다.

컬러를 on/off하는 예제를 포함하고 있습니다.


_17_logger_color.py

import datetime
import sys
import os
import time
import logging
import colorlog
from logging import FileHandler
from logging import handlers

class CustomLog:
	def __init__(self):
		pass
		
	def create(self,logfolder='', app_name=__name__, logprefix='log_', NEED_BACKUP_FILE = True, NEED_SCREEN_AND_FILE = True, level=logging.DEBUG, format='[%(asctime)s] %(levelname)s [%(filename)s.%(funcName)s:%(lineno)d] %(message)s', maxBytes=10*1024*1024, backupCount = 10, encoding='utf-8', color=True):
		LOG_PREFIX = logprefix
		LOG_FOLDER_NAME = logfolder
		# 로그 파일 핸들러
		now = datetime.datetime.now().isoformat()[:10]
		logf = LOG_PREFIX + now + ".log"
		if LOG_FOLDER_NAME!='' and not os.path.exists(LOG_FOLDER_NAME):
			os.makedirs(LOG_FOLDER_NAME)
		logf = os.path.join(LOG_FOLDER_NAME, logf)
		logger = self.getLogger(logf, app_name, NEED_BACKUP_FILE, NEED_SCREEN_AND_FILE, level, format, maxBytes, backupCount, encoding, color)
		logger.logfilename_ = logf
		return logger

	def getLogger(self, filename, app_name, NEED_BACKUP_FILE, NEED_SCREEN_AND_FILE, level, format, maxBytes, backupCount, encoding, color):
		if color :
			self.logger = colorlog.getLogger(app_name)
		else:
			self.logger = logging.getLogger(app_name)
		
		self.logger.handlers.clear()
		self.logger.propagate = False
		# log level은 아래 순서에 따른다. setLevel 과 같거나 큰 출력만 나오게 된다.
		# logger.setLevel(logging.CRITICAL) 인 경우 logger.critical() 만 나온다
		#
		# logger.debug("debug")
		# logger.info("info")
		# logger.warning("warning")
		# logger.error("error")
		# logger.critical("critical")
		self.logger.setLevel(level)

		# 포맷을 결정한다. 좀더 자세한 정보는 다음 링크를 참조한다
		# https://docs.python.org/3/library/logging.html#logrecord-attributes
		if color :
			logFormatter = colorlog.ColoredFormatter('%(log_color)s'+format)
		else :
			logFormatter = logging.Formatter(format)
		
		if NEED_BACKUP_FILE == True:
			rotatingHandler = handlers.RotatingFileHandler(filename=filename, maxBytes=maxBytes, backupCount = backupCount, encoding=encoding)
			rotatingHandler.setFormatter(logFormatter)
			self.logger.addHandler(rotatingHandler)
		else:
			fileHandler = logging.FileHandler(filename)
			fileHandler.setFormatter(logFormatter)
			self.logger.addHandler(fileHandler)

		# StreamHandler 는 self.logger.critical("critical") 이런 형태의 로그가 화면으로도 나오고 file로도 저장이 되도록 한다
		if NEED_SCREEN_AND_FILE == True:
			streamHandler = logging.StreamHandler()
			streamHandler.setFormatter(logFormatter)
			self.logger.addHandler(streamHandler)
		return self.logger
	
if __name__ == "__main__":
	logger = CustomLog().create('log')
	print("test")
	logger.debug("debug test")
	logger.info("info test")
	logger.warning("warning test")
	logger.error("error test")
	logger.critical("critical test")
	'''
	# other file
	import _17_logger_color
	logger = _17_logger_color.CustomLog().create('log',__name__)
	if __name__ == "__main__":
		logger.debug("debug test")
		logger.info("info test")
		logger.warning("warning test")
		logger.error("error test")
		logger.critical("critical test")
	'''


_17_logger_color_test.py

import _17_logger_color
import _17_logger_color_test_2

logger = _17_logger_color.CustomLog().create('log',__name__)

if __name__ == "__main__":
	_17_logger_color_test_2.noncolor_test()

	logger.debug("debug test")
	logger.info("info test")
	logger.warning("warning test")
	logger.error("error test")
	logger.critical("critical test")
	
	logger = _17_logger_color.CustomLog().create('log',__name__,color=False)
	logger.debug("MAIN color false test")
	logger.info("info test")
	logger.warning("warning test")
	logger.error("error test")
	logger.critical("critical test")
	
	_17_logger_color_test_2.noncolor_test()


_17_logger_color_test_2.py

import _17_logger_color

logger = _17_logger_color.CustomLog().create('log',__name__,color=False)

def noncolor_test():
	logger.debug("debug test 2")
	logger.info("info test 2")
	logger.warning("warning test 2")
	logger.error("error test 2")
	logger.critical("critical test 2")

 

실행결과



참고할만한 링크

2020년 11월 1일 일요일

solving print log twice in python (파이썬에서 로그 두번씩 출력되는 문제 해결)


앞에서 로그를 사용하게 쉽게 작업해보았습니다. 아래 소스를 기반으로 class도 만들어 봤습니다.

https://swlock.blogspot.com/2019/04/python-logging-using-logging-in-python.html

그런데 사용중에 문제가 발생하였습니다.

로그가 두번씩 출력되는 현상입니다. 일단 문제의 상황을 간단하게 예제로 만들어 보았습니다.


customlog.py

import datetime
import sys
import os
import time
import logging
from logging import FileHandler
from logging import handlers

#https://swlock.blogspot.com/2019/04/python-logging-using-logging-in-python.html
class CustomLog:
    def __init__(self):
        pass
        
    def create(self,logfolder='',app_name=__name__,logprefix='log_'):
        LOG_PREFIX = logprefix
        LOG_FOLDER_NAME = logfolder
        # 로그 파일 핸들러
        now = datetime.datetime.now().isoformat()[:10]
        logf = LOG_PREFIX + now + ".log"
        if LOG_FOLDER_NAME!='' and not os.path.exists(LOG_FOLDER_NAME):
            os.makedirs(LOG_FOLDER_NAME)
        logf = os.path.join(LOG_FOLDER_NAME, logf)
        logger = self.getLogger(logf, app_name)
        return logger

    def getLogger(self, filename, app_name, NEED_BACKUP_FILE = True, NEED_SCREEN_AND_FILE = True, level=logging.DEBUG, format='%(asctime)s,%(message)s', maxBytes=10*1024*1024, backupCount = 10, encoding='utf-8'):
        self.logger = logging.getLogger(app_name)
        # log level은 아래 순서에 따른다. setLevel 과 같거나 큰 출력만 나오게 된다.
        # logger.setLevel(logging.CRITICAL) 인 경우 logger.critical() 만 나온다
        #
        # logger.debug("debug")
        # logger.info("info")
        # logger.warning("warning")
        # logger.error("error")
        # logger.critical("critical")
        self.logger.setLevel(level)

        # 포맷을 결정한다. 좀더 자세한 정보는 다음 링크를 참조한다
        # https://docs.python.org/3/library/logging.html#logrecord-attributes
        logFormatter = logging.Formatter(format)

        if NEED_BACKUP_FILE == True:
            rotatingHandler = handlers.RotatingFileHandler(filename=filename, maxBytes=maxBytes, backupCount = backupCount, encoding=encoding)
            rotatingHandler.setFormatter(logFormatter)
            self.logger.addHandler(rotatingHandler)
        else:
            fileHandler = logging.FileHandler(filename)
            fileHandler.setFormatter(logFormatter)
            self.logger.addHandler(fileHandler)

        # StreamHandler 는 self.logger.critical("critical") 이런 형태의 로그가 화면으로도 나오고 file로도 저장이 되도록 한다
        if NEED_SCREEN_AND_FILE == True:
            streamHandler = logging.StreamHandler()
            streamHandler.setFormatter(logFormatter)
            self.logger.addHandler(streamHandler)
        return self.logger

if __name__ == "__main__":
    logger = CustomLog().create('log')
    print("test")
    logger.debug("debug test")
    logger.info("info test")
    logger.warning("warning test")
    logger.error("error test")
    logger.critical("critical test")


logtest2.py

import customlog

test2 = 1
logger = customlog.CustomLog().create('Log')
print("log test2")
logger.debug("debug test")
logger.info("info test")
logger.warning("warning test")
logger.error("error test")
logger.critical("critical test")


logtest1.py

import customlog
import logtest2

logger = customlog.CustomLog().create('Log')
print("logtest1")
print(logtest2.test2)
logger.debug("debug test")
logger.info("info test")
logger.warning("warning test")
logger.error("error test")
logger.critical("critical test")


test 결과

>python logtest1.py
log test2
2020-11-01 13:56:43,674,debug test
2020-11-01 13:56:43,676,info test
2020-11-01 13:56:43,676,warning test
2020-11-01 13:56:43,677,error test
2020-11-01 13:56:43,678,critical test
logtest1
1
2020-11-01 13:56:43,681,debug test
2020-11-01 13:56:43,681,debug test
2020-11-01 13:56:43,682,info test
2020-11-01 13:56:43,682,info test
2020-11-01 13:56:43,684,warning test
2020-11-01 13:56:43,684,warning test
2020-11-01 13:56:43,687,error test
2020-11-01 13:56:43,687,error test
2020-11-01 13:56:43,688,critical test
2020-11-01 13:56:43,688,critical test


logtest1.py에서 출력하는 log들이 두번씩 출력되게 됩니다.


원인

imoprt logtest2에 의해 customlog의 create()가 두번 호출 되었기 때문입니다.

logger = customlog.CustomLog().create('Log')

분석을 해봐도 CustomLog의 instance가 두번 생성되는것은 아닌 상황이고, handler가 두번 붙어있는건 맞지만 handler를 초기화 해줘도 실제 초기화 되지 않았습니다.


해결 방법

propagate 값을 False로 설정하여 계층화된 로그의 내용이 모이지 않도록 합니다.

그리고 log 처리기에 각각의 이름을 붙여줍니다.


전체 소스

propagate = False 추가함

customlog.py

import datetime
import sys
import os
import time
import logging
from logging import FileHandler
from logging import handlers

#https://swlock.blogspot.com/2019/04/python-logging-using-logging-in-python.html
class CustomLog:
    def __init__(self):
        pass
        
    def create(self,logfolder='',app_name=__name__,logprefix='log_'):
        LOG_PREFIX = logprefix
        LOG_FOLDER_NAME = logfolder
        # 로그 파일 핸들러
        now = datetime.datetime.now().isoformat()[:10]
        logf = LOG_PREFIX + now + ".log"
        if LOG_FOLDER_NAME!='' and not os.path.exists(LOG_FOLDER_NAME):
            os.makedirs(LOG_FOLDER_NAME)
        logf = os.path.join(LOG_FOLDER_NAME, logf)
        logger = self.getLogger(logf, app_name)
        return logger

    def getLogger(self, filename, app_name, NEED_BACKUP_FILE = True, NEED_SCREEN_AND_FILE = True, level=logging.DEBUG, format='%(asctime)s,%(message)s', maxBytes=10*1024*1024, backupCount = 10, encoding='utf-8'):
        self.logger = logging.getLogger(app_name)
        self.logger.propagate = False
        # log level은 아래 순서에 따른다. setLevel 과 같거나 큰 출력만 나오게 된다.
        # logger.setLevel(logging.CRITICAL) 인 경우 logger.critical() 만 나온다
        #
        # logger.debug("debug")
        # logger.info("info")
        # logger.warning("warning")
        # logger.error("error")
        # logger.critical("critical")
        self.logger.setLevel(level)

        # 포맷을 결정한다. 좀더 자세한 정보는 다음 링크를 참조한다
        # https://docs.python.org/3/library/logging.html#logrecord-attributes
        logFormatter = logging.Formatter(format)

        if NEED_BACKUP_FILE == True:
            rotatingHandler = handlers.RotatingFileHandler(filename=filename, maxBytes=maxBytes, backupCount = backupCount, encoding=encoding)
            rotatingHandler.setFormatter(logFormatter)
            self.logger.addHandler(rotatingHandler)
        else:
            fileHandler = logging.FileHandler(filename)
            fileHandler.setFormatter(logFormatter)
            self.logger.addHandler(fileHandler)

        # StreamHandler 는 self.logger.critical("critical") 이런 형태의 로그가 화면으로도 나오고 file로도 저장이 되도록 한다
        if NEED_SCREEN_AND_FILE == True:
            streamHandler = logging.StreamHandler()
            streamHandler.setFormatter(logFormatter)
            self.logger.addHandler(streamHandler)
        return self.logger

if __name__ == "__main__":
    logger = CustomLog().create('log')
    print("test")
    logger.debug("debug test")
    logger.info("info test")
    logger.warning("warning test")
    logger.error("error test")
    logger.critical("critical test")


__name__ 추가함

logtest2.py

import customlog

test2 = 1
logger = customlog.CustomLog().create('Log',__name__)
print("log test2")
logger.debug("debug test")
logger.info("info test")
logger.warning("warning test")
logger.error("error test")
logger.critical("critical test")

__name__ 추가함

logtest1.py

import customlog
import logtest2

logger = customlog.CustomLog().create('Log',__name__)
print("logtest1")
print(logtest2.test2)
logger.debug("debug test")
logger.info("info test")
logger.warning("warning test")
logger.error("error test")
logger.critical("critical test")


실행결과

C:\Users\USER\Documents\python\grammer>python logtest1.py
log test2
2020-11-01 14:17:13,104,debug test
2020-11-01 14:17:13,106,info test
2020-11-01 14:17:13,107,warning test
2020-11-01 14:17:13,108,error test
2020-11-01 14:17:13,108,critical test
logtest1
1
2020-11-01 14:17:13,111,debug test
2020-11-01 14:17:13,112,info test
2020-11-01 14:17:13,113,warning test
2020-11-01 14:17:13,114,error test
2020-11-01 14:17:13,117,critical test


추가로 핸들러를 초기화 하는것도 참고 바랍니다.

아래 colored log 에서는 create할때 handler를 clear하는 코드를 넣었습니다.

2019년 4월 21일 일요일

python 에서 logging 사용하기(using logging in python)


python3에서 로그를 사용하기 위한 logging이라는 패키지가 있습니다. 핸들러도 있고 설명도 복잡해서 뭐라는건지 잘 이해가 안되어서 자주 사용할만한 클래스를 만들었습니다. 그럼 소스 코드부터 보고 가시겠습니다.


import logging
import os
from logging import handlers

class CustomLog:
    def __init__(self):
        pass

    def getLogger(self, filename, NEED_BACKUP_FILE = True, NEED_SCREEN_AND_FILE = True, level=logging.DEBUG, format='%(asctime)s,%(message)s', maxBytes=10*1024*1024, backupCount = 10, encoding='utf-8'):
        self.logger = logging.getLogger()
        # log level은 아래 순서에 따른다. setLevel 과 같거나 큰 출력만 나오게 된다.
        # logger.setLevel(logging.CRITICAL) 인 경우 logger.critical() 만 나온다
        #
        # logger.debug("debug")
        # logger.info("info")
        # logger.warning("warning")
        # logger.error("error")
        # logger.critical("critical")
        self.logger.setLevel(level)

        # 포맷을 결정한다. 좀더 자세한 정보는 다음 링크를 참조한다
        # https://docs.python.org/3/library/logging.html#logrecord-attributes
        logFormatter = logging.Formatter(format)

        if NEED_BACKUP_FILE == True:
            rotatingHandler = handlers.RotatingFileHandler(filename=filename, maxBytes=maxBytes, backupCount = backupCount, encoding=encoding)
            rotatingHandler.setFormatter(logFormatter)
            self.logger.addHandler(rotatingHandler)
        else:
            fileHandler = logging.FileHandler(filename)
            fileHandler.setFormatter(logFormatter)
            self.logger.addHandler(fileHandler)

        # StreamHandler 는 self.logger.critical("critical") 이런 형태의 로그가 화면으로도 나오고 file로도 저장이 되도록 한다
        if NEED_SCREEN_AND_FILE == True:
            streamHandler = logging.StreamHandler()
            streamHandler.setFormatter(logFormatter)
            self.logger.addHandler(streamHandler)
        return self.logger

1. 파일에 기록하기

로깅 함수를 사용하는 이유는 파일에 기록을 하려는 목적이 있습니다. 화면에만 하고 싶으면 print 함수로도 충분합니다.
파일 핸들러를 등록하는것은 아래 함수 입니다. 물론 기본으로 등록하지는 않고 NEED_BACKUP_FILE false 일 경우에만 등록하게 됩니다.
            fileHandler = logging.FileHandler(filename)
            fileHandler.setFormatter(logFormatter)
            self.logger.addHandler(fileHandler)
NEED_BACKUP_FILE == True 인 경우 백업 파일이란것을 만들게 되는데 파일이 일정크기가 되면 백업을 시도합니다. 해당 기능을 사용하고 싶지 않으면 False 처리하면 됩니다.

2. 로그의 레벨 시스템

기본적으로 알아야 하는 내용은 아래 부분입니다.
        # logger.debug("debug")
        # logger.info("info")
        # logger.warning("warning")
        # logger.error("error")
        # logger.critical("critical")
레벨이 존재하고 logger.info("출력을 원하는 텍스트") 라고 하면 info level로 로그가 화면에 출력이 되어야 하지만 실제는 로그 시스템의 level이 뭘로 되어있느냐에 따라 출력이 될 수도 안될 수도 있습니다. 즉 logger.setLevel(level) 함수에 의해 출력 레벨이 결정 되는데 해당 값보다는 큰것만 출력이 되게 됩니다.
이해가 잘안되면 level=logging.DEBUG 이 기본값으로 설정했으므로 모든 문구가 출력이 됩니다.

3. 출력 포맷

출력 포맷은 아래 함수에 의해 결정 됩니다.
 logFormatter = logging.Formatter(format)
기본값으로는 아래와같은 형태로 되어 있어서 시간+로그가 출력되도록 되어있습니다.
format='%(asctime)s,%(message)s'

4. 화면으로의 출력

기본은 파일에만 로그가 출력됩니다. 일반적으로는 화면에도 출력을 원할때가 있습니다.
이때 NEED_SCREEN_AND_FILE True 값을 설정하면 화면에도 출력이 가능하도록 핸들러를 등록합니다.
        if NEED_SCREEN_AND_FILE == True:
            streamHandler = logging.StreamHandler()
            streamHandler.setFormatter(logFormatter)
            self.logger.addHandler(streamHandler)

5. 사용 예제


import os
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../util/')))
import customlog

if __name__ == "__main__":
    logname = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test.log')
    logsystem = customlog.CustomLog()
    logger = logsystem.getLogger(logname)

    print("test")
    logger.debug("debug test")
    logger.info("info test")
    logger.warning("warning test")
    logger.error("error test")
    logger.critical("critical test")

소스에서 sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../util/'))) 이 부분은 customlog의 path가 같은 폴더에 있지 않아서 import 하기 위해서 추가된 코드 입니다.
logname = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test.log') 저장하고자 하는 파일 이름을 설정합니다.
logger = logsystem.getLogger(logname)을 하게 되면 기본적으로 파일 출력과 화면을 동시에 지원하며 backup 파일도 지원되는 logger를 만들게 됩니다.

화면 출력은 아래와 같이 나옵니다.

test
2019-04-21 18:23:58,166,debug test
2019-04-21 18:23:58,167,info test
2019-04-21 18:23:58,169,warning test
2019-04-21 18:23:58,179,error test
2019-04-21 18:23:58,181,critical test

파일은 아래와 같이 나오게 됩니다.
2019-04-21 18:23:58,166,debug test
2019-04-21 18:23:58,167,info test
2019-04-21 18:23:58,169,warning test
2019-04-21 18:23:58,179,error test
2019-04-21 18:23:58,181,critical test