[TIP] 에러 발생할 때 Logging 파일 생성 및 적재하는 코드

2020. 11. 15. 23:26꿀팁 분석 환경 설정/파이썬 개발 팁

728x90
728x90

파이썬에서 클래스로 짜거나 함수로 짜거나 하였을 때, 중간에 에러가 발생하는 경우가 있다.

이것들을 따로 로깅을 하지 않고 주피터 노트북에서 계속 돌린다면, 실수로 노트북이 꺼졌을 때나 잘 찾을 수가 없게 된다.

 

그래서 이번에는 함수나 클래스에서 에러가 발생했을 때 로그를 적재하는 파일 생성 및 계속해서 적재하는 코드를 만들어 봤다. 

 

예를 들어 아래 함수처럼 divide라는 나눗셈 함수를 만들었는데, 들어오는 데이터에 따라서 에러가 발생하는 경우가 있다.

이때 어떠한 a 와 b 였으며, 무슨 에러인지를 표현하는 것을 공유한다.

@log_error("./log.txt")
def divde(a,b) :
    return a/b

아래가 풀 코드이다.

이 함수를 통해서 로그를 생성 및 argument를 적재하여 확인할 수 있다.

import logging
import functools , os

"""
usage : 

@log_error("./log.txt")
def divde(a,b) :
    return a/b
        
"""

def _generate_log(path):
    """
    Create a logger object
    :param path: Path of the log file.
    :return: Logger object.
    """
    # Create a logger and set the level.
    logger = logging.getLogger('LogError')
    logger.setLevel(logging.ERROR)
    file_handler = logging.FileHandler(path)
    log_format = '%(levelname)s %(asctime)s %(message)s'
    formatter = logging.Formatter(log_format)
    file_handler.setFormatter(formatter)
    logger.handlers = []       # No duplicated handlers
    logger.propagate = False 
    logger.addHandler(file_handler)
    return logger


def log_error(path='<path>/log.error.log'):
    """
    We create a parent function to take arguments
    :param path:
    :return:
    """

    def error_log(func):

        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                logger = _generate_log(path)
                error_msg = f"And error has occurred at / ```{func.__qualname__  }``` \n args : {args} \n kwargs : {kwargs}"
                logger.exception(error_msg)
                return e  # Or whatever message you want.

        return wrapper

    return error_log

예시는 다음과 같다.

@log_error("./log.txt")
def divde(a,b) :
    return a/b
    
divide(a=10,b=0)

에러가 divde 함수에서 , a= 10, b=0이라는 것을 확인할 수 있다.

 

class에서는 다음과 같다

class ABC(object) :
    def __init__(self,) :
        pass
    
    @log_error("./error_check.txt")
    def a(self,dd):
        raise
        return 
    
    @log_error("./error_check.txt")
    def b(self,dd):
        raise 
        return 
ABC().a("hi")

ABC.b 에서 먼가를 넣었는데, RuntimeError('No active exception to reraise')가 발생한 것이다 

 

이런 식으로 로깅을 통해서 문제가 되는 점을 적재하고, 추후에 확인을 빠르게 할 수 있을 것이다

728x90