使用Python的logging模块记录所有异常和错误

49

我想检查一个特定的后台文件中是否有错误,但标准错误流被前台程序控制,导致该文件中的错误未显示。不过,我可以使用 logging 模块并将输出写入文件。我想知道如何使用它来记录所有异常、错误及其跟踪信息。


5
可能是在Python中记录未捕获异常的重复问题 - Trevor Boyd Smith
3个回答

91

记录程序中抛出的所有异常可能不是个好主意,因为Python也会用异常来进行正常控制流程。

因此,你应该只记录未捕获的异常。一旦有异常对象,你可以使用日志器的 exception() 方法 轻松做到这一点。

要处理所有未捕获的异常,你可以将脚本入口点放在 try...except 块中,或通过重新分配sys.excepthook()来安装自定义异常处理程序:

import logging
import sys

logger = logging.getLogger('mylogger')
# Configure logger to write to a file...

def my_handler(type, value, tb):
    logger.exception("Uncaught exception: {0}".format(str(value)))

# Install exception handler
sys.excepthook = my_handler

# Run your main script here:
if __name__ == '__main__':
    main()

6
sys.__excepthook__(type, value, tb) 添加到您的 my_handler 中,以便它可以在异常时处理默认操作,这不是一个好主意吗? - tro
2
@Ferdinand Beyer:很好。在我的情况下,使用 logger.exception("Uncaught exception: {0}: {1}".format(str(value.__class__.__name__), str(value))) 输出了 ERROR - Uncaught exception: IndexError: list index out of range 并且由于某些原因打印了“None”。我怎样才能获取完整的回溯信息呢?‘tb’似乎是一个回溯对象,但是 traceback.print_tb(tb) 也只会输出None - bioslime
6
请参考这个配方,它依赖于exc_info关键字参数来记录回溯信息。看起来它只能与logger.errorlogger.critical一起使用,而不能与logger.exception一起使用。 - j08lue
1
以上代码对我无效。将 main() 替换为 hello ==== "Hello" 仍会导致堆栈跟踪被打印到控制台。 - cclauss
这个回答实际上并没有回答问题,虽然 OP 可能满意,但从 Google 进来的人可能不会。即使被某些东西捕获了,想要记录 所有 引发的异常也是有合理的原因的。 - RuRo
5
我同意这个答案:https://dev59.com/K2025IYBdhLWcg3wEhnr#16993115 - Zhou Hongbo

3
import sys
import logging
import traceback

# log uncaught exceptions
def log_exceptions(type, value, tb):
    for line in traceback.TracebackException(type, value, tb).format(chain=True):
        logging.exception(line)
    logging.exception(value)

    sys.__excepthook__(type, value, tb) # calls default excepthook

sys.excepthook = log_exceptions

这将记录并继续正常操作。 - JeffCharter

3
受到主要答案的启发 + 如何使用Python日志模块写入文件? + 在excepthook中打印原始异常, 这里是如何将完整的回溯信息写入文件test.log,就像在控制台上打印的一样:
import logging, sys, traceback
logger = logging.getLogger('logger')
fh = logging.FileHandler('test.log')
logger.addHandler(fh)
def exc_handler(exctype, value, tb):
    logger.exception(''.join(traceback.format_exception(exctype, value, tb)))
sys.excepthook = exc_handler
print("hello")
1/0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接