[Python] 파이썬에서 캐치되지 않은 예외를 로깅하기


Answers

다음은 몇 가지 다른 트릭을 포함하는 작은 예제입니다.

import sys
import logging
logger = logging.getLogger(__name__)
handler = logging.StreamHandler(stream=sys.stdout)
logger.addHandler(handler)

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

    logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))

sys.excepthook = handle_exception

if __name__ == "__main__":
    raise RuntimeError("Test unhandled")
  • Ctrl + C로 콘솔 파이썬 프로그램을 종료 할 수 있도록 KeyboardInterrupt를 무시하십시오.

  • 예외를 포맷하기위한 파이썬의 로깅 모듈에 전적으로 의존하십시오.

  • 예제 핸들러와 함께 사용자 정의 로거를 사용하십시오. 이 핸들러는 처리되지 않은 예외를 stderr가 아닌 stdout으로 변경하지만이 스타일의 모든 핸들러를 logger 객체에 추가 할 수 있습니다.

Question

캐치되지 않은 예외를 stderr 대신 logging 모듈을 통해 출력하도록하려면 어떻게해야합니까?

이 일을하는 가장 좋은 방법은 다음과 같을 것입니다.

try:
    raise Exception, 'Throwing a boring exception'
except Exception, e:
    logging.exception(e)

그러나 예외 상황이 잡히지 않을 때마다 logging.exception(...) 이 자동으로 호출 된 경우 상황이 정말 좋을 것입니다.




try...except 블록에 응용 프로그램 항목 호출을 래핑하면 캡처되지 않은 모든 예외를 잡아서 기록 할 수 있습니다. 예 : 대신 :

if __name__ == '__main__':
    main()

이 작업을 수행:

if __name__ == '__main__':
    try:
        main()
    except Exception as e:
        logger.exception(e)
        raise



@ gnu_lorien의 대답이 나에게 좋은 시작점을 주었지만, 첫 번째 예외는 내 프로그램이 충돌합니다.

@handle_error 로 장식 된 함수의 예외를 자동으로 기록하는 사용자 지정 (및 / 또는) 개선 된 솔루션이 제공 @handle_error .

import logging

__author__ = 'ahmed'
logging.basicConfig(filename='error.log', level=logging.DEBUG)


def handle_exception(exc_type, exc_value, exc_traceback):
    import sys
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
    logging.critical(exc_value.message, exc_info=(exc_type, exc_value, exc_traceback))


def handle_error(func):
    import sys

    def __inner(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception, e:
            exc_type, exc_value, exc_tb = sys.exc_info()
            handle_exception(exc_type, exc_value, exc_tb)
        finally:
            print(e.message)
    return __inner


@handle_error
def main():
    raise RuntimeError("RuntimeError")


if __name__ == "__main__":
    for _ in xrange(1, 20):
        main()



왜 안돼 :

import sys
import logging
import traceback

def log_except_hook(*exc_info):
    text = "".join(traceback.format_exception(*exc_info))
    logging.error("Unhandled exception: %s", text)

sys.excepthook = log_except_hook

None()

위에 보이는 sys.excepthook 의 출력 결과는 다음과 같습니다.

$ python tb.py
ERROR:root:Unhandled exception: Traceback (most recent call last):
  File "tb.py", line 11, in <module>
    None()
TypeError: 'NoneType' object is not callable

다음은 sys.excepthook 주석 sys.excepthook 출력입니다.

$ python tb.py
Traceback (most recent call last):
  File "tb.py", line 11, in <module>
    None()
TypeError: 'NoneType' object is not callable

유일한 차이점은 이전에는 ERROR:root:Unhandled exception: 첫 번째 줄의 시작 부분에.