python - 在Python中继承记录器名称

标签 python logging

我正在尝试在 python 中记录未捕获的异常。为此,我在 __init__.py 中设置 sys.excepthook,如下所示。

import sys
import logging
import traceback


def log_except_hook(*exc_info):
    logger = logging.getLogger(__name__)
    text = "".join(traceback.format_exception(*exc_info))
    logger.critical(f"Unhandled exception:\n{text}")


sys.excepthook = log_except_hook

我的问题是,当我运行一个进程并发生异常时,记录的异常中的模块名称是包含代码的文件夹的名称(在本例中是src),而不是发生该错误的函数的名称(本例中为 foo_product_an_error)。请在下面找到一个示例:

2019-10-09 18:55:48,638 src CRITICAL: Unhandled exception:
Traceback (most recent call last):
  File "/Users/ivallesp/Projects/Project_Folder/main.py", line 109, in <module>
    foo_function(7)
  File "/Users/ivallesp/Projects/Project_Folder/src/new_module.py", line 8, in foo_function
    foo_produce_an_error(x)
  File "/Users/ivallesp/Projects/Project_Folder/src/new_module.py", line 12, in foo_produce_an_error
    x / 0
ZeroDivisionError: division by zero

如何进行日志记录以显示第一个日志记录行中发生错误的模块和函数名称?

最佳答案

您没有提供足够的信息来回答问题 - 例如,您如何配置日志记录(特别是使用的格式字符串/格式化程序)。我可以通过一个例子来说明如何实现总体上期望的结果。假设模块 failfunc 中有一个失败的函数:

# failfunc.py
def the_failing_func():
    1 / 0

然后,您的主要脚本可能是:

# logtest_ue.py
import logging
import sys

from failfunc import the_failing_func

def log_except_hook(*exc_info):
    logger = logging.getLogger(__name__)
    tb = exc_info[-1]
    # get the bottom-most traceback entry
    while tb.tb_next:
        tb = tb.tb_next
    modname = tb.tb_frame.f_globals.get('__name__')
    funcname = tb.tb_frame.f_code.co_name
    logger.critical('Unhandled in module %r, function %r: %s',
                    modname, funcname, exc_info[1], exc_info=exc_info)

sys.excepthook = log_except_hook

def main():
    the_failing_func()

if __name__ == '__main__':
    logging.basicConfig(format='%(levelname)s %(message)s')
    sys.exit(main())

运行时,它会打印

CRITICAL Unhandled in module 'failfunc', function 'the_failing_func': division by zero
Traceback (most recent call last):
  File "logtest_ue.py", line 23, in <module>
    sys.exit(main())
  File "logtest_ue.py", line 19, in main
    the_failing_func()
  File "/home/vinay/projects/scratch/failfunc.py", line 2, in the_failing_func
    1 / 0
ZeroDivisionError: division by zero

请注意使用 exc_info 关键字参数将回溯记录到日志中的稍微简单的方法。另请注意,在这种情况下,正常的模块和函数名称(可以使用格式字符串中的 %(module)s%(funcName)s 显示)将是 sys.excepthook 指向的值,而不是实际发生异常的值。对于这些,您必须按照我演示的方式使用回溯对象来获取最底层的框架(实际发生异常的位置)并从该框架中获取模块和函数名称。

关于python - 在Python中继承记录器名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58308960/

相关文章:

java - 从 Java 调用 python 模块时出错

python - 从同一模块动态实例化类会导致 main 运行两次

java - 我们如何使用 logback.xml 和 MDC 在 spring-boot 日志记录中获取用户请求、响应、请求 id 以及进程 id?

java - 具有 logback 条件的多个根记录器

java - 如何控制客户端库中的日志记录级别?

logging - 将Scribe集中式日志记录输出发送到Elasticsearch的最佳方法

python - 将文本文件中单独标题下的列保存到单独的列表中

python - 如何从 Py_CompileString 打印出错误(包括语法)?

python - API网关未调用 chalice 端点

objective-c - 记录 NSNotifications