반응형
이글을 통해 Python에서 제공하는 중요 기능중 하나인 Decorator를 활용한 Log Decorator관련해서 정리해보고자 한다.
Decorator 활용이 Log에 적절한 이유는
Decorator는 Python 설명을 보면 잘 나와 있듯이 함수를 감싸는 기능을 제공하기 때문에 실행전, 실행후에 일관성있게 정의하여 적용하고자 할때 Decorator만 한 것이 없다.
즉 log 입장으로 보면, 함수 실행전과 실행후에 대한 로그를 한번에 구성할 수 있어서 매우 유용하다고 할 수 있겠다.
그리고 개발한 프로그램을 서비스할 때 문제 분석을 위해 로그를 기록해야 하는 경우 log를 위한 코드를 추가를 해야하기 때문에 Decorator를 활용하기가 제격이라고 할 수 있다.
가장 간단하게 만들수 있는 log Decorator는 다음과 같다.
def log(func):
def wrap_log(*args, **kwargs):
name = func.__name__
result = func(*args, **kwargs) # 실제 함수를 호출하는 구분
print('log decorator',name, result)
return func
return wrap_log
@log
def sum(a):
return a+a
if __name__ == "__main__":
value = sum(2)
즉 실행 함수를 func로 가지고 와서 이를 실행하고 실행 결과를 반환해 주게 된다.
이를 활용하여 로깅을 실행전, 실행후로 정의할 수 있고, try/except를 활용하여 문제의 원인을 기록해 쉽게 관리가 가능하다.
Github을 찾아보던중 아래와 같이 로그 데코레이터를 구현해 놓은 소스가 있어 코드는 백업 목적으로 아래 남겨둔다.
log.py
import logging
import os
class CustomFormatter(logging.Formatter):
""" Custom Formatter does these 2 things:
1. Overrides 'funcName' with the value of 'func_name_override', if it exists.
2. Overrides 'filename' with the value of 'file_name_override', if it exists.
"""
def format(self, record):
if hasattr(record, 'func_name_override'):
record.funcName = record.func_name_override
if hasattr(record, 'file_name_override'):
record.filename = record.file_name_override
return super(CustomFormatter, self).format(record)
def get_logger(log_file_name, log_sub_dir=""):
""" Creates a Log File and returns Logger object """
windows_log_dir = 'c:\\logs_dir\\'
linux_log_dir = '/logs_dir/'
# Build Log file directory, based on the OS and supplied input
log_dir = windows_log_dir if os.name == 'nt' else linux_log_dir
log_dir = os.path.join(log_dir, log_sub_dir)
# Create Log file directory if not exists
if not os.path.exists(log_dir):
os.makedirs(log_dir)
# Build Log File Full Path
logPath = log_file_name if os.path.exists(log_file_name) else os.path.join(log_dir, (str(log_file_name) + '.log'))
# Create logger object and set the format for logging and other attributes
logger = logging.Logger(log_file_name)
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(logPath, 'a+')
""" Set the formatter of 'CustomFormatter' type as we need to log base function name and base file name """
handler.setFormatter(CustomFormatter('%(asctime)s - %(levelname)-10s - %(filename)s - %(funcName)s - %(message)s'))
logger.addHandler(handler)
# Return logger object
return logger
반응형
'Python' 카테고리의 다른 글
VSCode - 쓸만한 무료 코파일럿(Copilot) (0) | 2024.03.26 |
---|---|
VSCode - Python 자동 주석 생성 autoDocstring (0) | 2024.03.25 |
Python - 왜 f-string을 쓰라는 걸까 "Formatting a regular string which could be a f-string" (0) | 2024.03.25 |
Python - -u PYTHONUNBUFFERED 사용 (0) | 2024.03.25 |
Python - Mocking/단위 테스트(Unit Test) 과 Django 활용 (0) | 2024.03.25 |