파이썬에서 포착되지 않은 예외 로깅
잡히지 않는 예외가 logging
아닌 모듈을 통해 어떻게 출력 stderr
됩니까?
이 작업을 수행하는 가장 좋은 방법은 다음과 같습니다.
try:
raise Exception, 'Throwing a boring exception'
except Exception, e:
logging.exception(e)
그러나 내 상황은 예외가 포착되지 않을 때마다 자동으로 호출 되면 정말 좋을 것 logging.exception(...)
입니다.
Ned가 지적했듯이 sys.excepthook
예외가 발생하여 포착되지 않을 때마다 호출됩니다. 이것의 실질적인 의미는 코드에서 sys.excepthook
원하는 것을 수행 하는 기본 동작을 무시할 수 있다는 것입니다 (사용 포함 logging.exception
).
짚맨 예를 들면 :
>>> import sys
>>> def foo(exctype, value, tb):
... print 'My Error Information'
... print 'Type:', exctype
... print 'Value:', value
... print 'Traceback:', tb
...
무시 sys.excepthook
:
>>> sys.excepthook = foo
명백한 구문 오류를 커밋하고 (콜론 제외) 사용자 지정 오류 정보를 다시 가져옵니다.
>>> def bar(a, b)
My Error Information
Type: <type 'exceptions.SyntaxError'>
Value: invalid syntax (<stdin>, line 1)
Traceback: None
에 대한 자세한 내용은 sys.excepthook
: http://docs.python.org/library/sys.html#sys.excepthook
다음은 몇 가지 다른 트릭을 포함하는 완전한 작은 예입니다.
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")
Console python 프로그램이 Ctrl + C로 종료 될 수 있도록 KeyboardInterrupt를 무시하십시오.
예외를 포맷하려면 파이썬의 로깅 모듈에 전적으로 의존하십시오.
예제 핸들러와 함께 사용자 정의 로거를 사용하십시오. 이것은 처리되지 않은 예외를 변경하여 stderr가 아닌 stdout으로 이동하지만, 동일한 스타일의 모든 핸들러를 로거 오브젝트에 추가 할 수 있습니다.
sys.excepthook
예외가 발생하지 않으면 메소드 가 호출됩니다. http://docs.python.org/library/sys.html#sys.excepthook
예외가 발생하여 포착되지 않으면 인터프리터는 세 개의 인수, 예외 클래스, 예외 인스턴스 및 추적 백 오브젝트와 함께 sys.excepthook을 호출합니다. 대화식 세션에서는 제어가 프롬프트로 리턴되기 직전에 발생합니다. 파이썬 프로그램에서 이것은 프로그램이 종료되기 직전에 발생합니다. 이러한 최상위 예외 처리는 sys.excepthook에 다른 3 개의 인수 함수를 할당하여 사용자 지정할 수 있습니다.
왜 안되 겠어요 :
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
주석 처리 된 출력입니다 .
$ 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:
첫 줄의 시작 부분에 있다는 것입니다.
Jacinda의 답변을 기반으로하지만 로거 객체를 사용하려면 다음을 수행하십시오.
def catchException(logger, typ, value, traceback):
logger.critical("My Error Information")
logger.critical("Type: %s" % typ)
logger.critical("Value: %s" % value)
logger.critical("Traceback: %s" % traceback)
# Use a partially applied function
func = lambda typ, value, traceback: catchException(logger, typ, value, traceback)
sys.excepthook = func
Wrap your app entry call in a try...except
block so you'll be able to catch and log (and perhaps re-raise) all uncaught exceptions. E.g. instead of:
if __name__ == '__main__':
main()
Do this:
if __name__ == '__main__':
try:
main()
except Exception as e:
logger.exception(e)
raise
Maybe you could do something at the top of a module that redirects stderr to a file, and then logg that file at the bottom
sock = open('error.log', 'w')
sys.stderr = sock
doSomething() #makes errors and they will log to error.log
logging.exception(open('error.log', 'r').read() )
Although @gnu_lorien's answer gave me good starting point, my program crashes on first exception.
I came with a customised (and/or) improved solution, which silently logs Exceptions of functions that are decorated with @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()
To answer the question from Mr.Zeus discussed in the comment section of the accepted answer, I use this to log uncaught exceptions in an interactive console (tested with PyCharm 2018-2019). I found out sys.excepthook
does not work in a python shell so I looked deeper and found that I could use sys.exc_info
instead. However, sys.exc_info
takes no arguments unlike sys.excepthook
that takes 3 arguments.
Here, I use both sys.excepthook
and sys.exc_info
to log both exceptions in an interactive console and a script with a wrapper function. To attach a hook function to both functions, I have two different interfaces depending if arguments are given or not.
Here's the code:
def log_exception(exctype, value, traceback):
logger.error("Uncaught exception occurred!",
exc_info=(exctype, value, traceback))
def attach_hook(hook_func, run_func):
def inner(*args, **kwargs):
if not (args or kwargs):
# This condition is for sys.exc_info
local_args = run_func()
hook_func(*local_args)
else:
# This condition is for sys.excepthook
hook_func(*args, **kwargs)
return run_func(*args, **kwargs)
return inner
sys.exc_info = attach_hook(log_exception, sys.exc_info)
sys.excepthook = attach_hook(log_exception, sys.excepthook)
The logging setup can be found in gnu_lorien's answer.
참고URL : https://stackoverflow.com/questions/6234405/logging-uncaught-exceptions-in-python
'IT박스' 카테고리의 다른 글
Rails 및 PostgreSQL에서 시간대를 모두 무시 (0) | 2020.06.07 |
---|---|
LINQ : "포함"및 Lambda 쿼리 (0) | 2020.06.07 |
안드로이드 자바; (0) | 2020.06.07 |
R 스크립트에서 전체적으로 경고를 표시하지 않는 방법 (0) | 2020.06.07 |
Razor의 동적 익명 유형으로 인해 RuntimeBinderException이 발생 함 (0) | 2020.06.07 |