Language/Python

[파이썬] 에러 로깅 클래스

nowkoes 2024. 9. 28. 00:00

Error Logging

개요

출처: https://docs.python.org/3/library/logging.html

 

  파이썬으로 프로그램을 개발하여 exe 파일로 빌드한 후 테스트할 때, 종종 콘솔창을 제외한 형태로 실행 파일을 만들곤 한다. 하지만 이 경우 오류가 발생하더라도 콘솔창이 없어 문제를 파악하기가 어렵다. 이러한 실행 파일의 런타임 환경 등에서 발생하는 오류를 기록하기 위해 사용하는 모듈이 바로 logging이다. 이번 시간에는 이 logging 모듈을 활용해, 프로그램 실행 중 에러가 발생하면 같은 디렉터리에 에러 내용을 담은 텍스트 파일을 자동으로 생성하는 클래스를 구현해 보겠다.


본문

 로깅 모듈을 통해 에러를 검출하고 처리하기 위한 최소한의 구성 요소는 다음과 같다. 

 

1. 로그 레벨: 로깅 모듈에서는 로그를 다음과 같은 레벨로 나눈다. 로그를 남길 메시지의 특성에 따라 아래의 다섯 가지 레벨 중 하나를 선택하면 된다. 

  • DEBUG: 디버깅 메시지. 세부적인 정보를 남기고 싶을 때 주로 사용
  • INFO: 일반적인 정보 메시지
  • WARNING: 경고 수준의 메시지. 프로그램이 정상적으로 동작하지만 주의가 필요한 상황을 알림
  • ERROR: 오류가 발생했을 때의 메시지. 문제로 인해 프로그램의 일부 기능이 제대로 동작하지 않을 때 사용
  • CRITICAL: 치명적인 오류 메시지. 프로그램이 더 이상 실행될 수 없는 상황

 

2. 로그 설정: 오류를 기록하려면 먼저 로그 파일을 설정해야 한다. 가장 기본적인 구성은 logging.basicConfig() 함수를 사용하여 파일에 로그를 저장하는 방식이다.

logging.basicConfig(
    filename='error_log.txt',  # 로그 파일명
    level=logging.ERROR,       # ERROR 이상의 로그만 기록
    format='%(asctime)s %(levelname)s: %(message)s'  # 로그 형식
)

 

3. 예외 처리: 프로그램에서 예외가 발생했을 때의 동작을 정의하는 부분이다. 예를 들어, 예외 상황이 발생했을 경우 경고창을 띄우고 앞서 설정한 로그 파일에 내용을 덮어 씌우는 형태로 쓸 수 있다. 이때 예외가 발생한 위치나 더 상세한 트레이스백(Traceback) 정보가 필요하면 exc_info 옵션을 사용할 수 있다.

def log_exception(exc_type, exc_value, exc_traceback):
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return

    logging.error(
        "An unhandled exception occurred",
        exc_info=(exc_type, exc_value, exc_traceback)
    )

    tkinter.messagebox.showerror(
        "Error",
        "An unexpected error occurred. Please check error_log.txt."
    )
    sys.exit(1)

 

4. hook 설정: hook는 프로그래밍에서 특정 이벤트가 발생할 때 실행되도록 미리 정의된 함수나 동작을 의미한다. 즉, 기본적으로 프로그램의 흐름에 개입할 수 있도록 설계된 지점이다. 파이썬에서는 프로그램 전역에서 발생하는 미처리된 예외를 처리하는 hook로 sys.excepthook를 사용할 수 있다.

sys.excepthook = ErrorLogging.log_exception # hook 지정

 

 필자의 경우엔 해당 내용들을 담아 클래스로 만들어 개발 중인 프로그램에 임포트하여 사용하고 있다. 이때 굳이 객체로 만들 필요는 없으므로 정적 클래스처럼 동작하게 메서드들을 static 키워드로 선언하였다.

import logging
import tkinter
import sys
import tkinter.messagebox

class ErrorLogging:
    @staticmethod
    def setup_logging(log_filename='error_log.txt'):
        logging.basicConfig(
            filename=log_filename,
            level=logging.ERROR,
            format='%(asctime)s %(levelname)s: %(message)s'
        )
    
    @staticmethod
    def log_exception(exc_type, exc_value, exc_traceback):
        if issubclass(exc_type, KeyboardInterrupt):
            sys.__excepthook__(exc_type, exc_value, exc_traceback)
            return

        logging.error(
            "An unhandled exception occurred",
            exc_info=(exc_type, exc_value, exc_traceback)
        )

        tkinter.messagebox.showerror(
            "Error",
            "An unexpected error occurred. Please check error_log.txt."
        )
        sys.exit(1)

    @staticmethod
    def setup_exception_hook():
        sys.excepthook = ErrorLogging.log_exception

 

 해당 클래스를 이용해 예외 적인 상황을 만들어 보면 다음과 같다.

import logging
import tkinter
import sys
import tkinter.messagebox

class ErrorLogging:
    @staticmethod
    def setup_logging(log_filename='error_log.txt'):
        logging.basicConfig(
            filename=log_filename,
            level=logging.ERROR,
            format='%(asctime)s %(levelname)s: %(message)s'
        )
    
    @staticmethod
    def log_exception(exc_type, exc_value, exc_traceback):
        if issubclass(exc_type, KeyboardInterrupt):
            sys.__excepthook__(exc_type, exc_value, exc_traceback)
            return

        logging.error(
            "An unhandled exception occurred",
            exc_info=(exc_type, exc_value, exc_traceback)
        )

        tkinter.messagebox.showerror(
            "Error",
            "An unexpected error occurred. Please check error_log.txt."
        )
        sys.exit(1)

    @staticmethod
    def setup_exception_hook():
        sys.excepthook = ErrorLogging.log_exception

if __name__ == "__main__":
    ErrorLogging.setup_logging()
    ErrorLogging.setup_exception_hook()

    print(asdfknxvxcv)


요약

logging
1. 정의: 로그를 기록하는 데 사용되는 모듈
2. 옵션
 a. 로그 레벨: 오류를 기록하는 레벨
 b. 로그 설정: logging.basicConfig()로 로그 파일 이름, 로그 레벨, 형식을 설정
 c. 예외 처리: try-except 구문에서 발생하는 예외를 logging.error(), 사용자 정의 함수 등으로 기록
 d. sys.excepthook: 프로그램 전역에서 발생하는 미처리 예외를 자동으로 기록하도록 설정

 

반응형