簡體   English   中英

在 Python 中繼承記錄器名稱

[英]Inherit logger name in Python

我正在嘗試在 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 ),而不是發生它的 function 的名稱( foo_produce_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

如何進行日志記錄以顯示第一個日志記錄行中發生錯誤的 function 的模塊和名稱?

您沒有提供足夠的信息來回答這個問題 - 例如,您如何配置日志記錄(特別是使用的格式字符串/格式化程序)。 我可以通過一個例子來說明如何總體上達到預期的結果。 假設您在模塊 failfunc 中有一個失敗的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關鍵字參數獲取日志回溯的稍微簡單的方法。 另請注意,在這種情況下,普通模塊和 function 名稱(可以在格式字符串中使用%(module)s%(funcName)s顯示)將是sys.excepthook指向的那些,而不是其中的值異常確實發生了。 對於那些,您必須按照我說明的方式使用回溯 object 來獲取最底部的幀(實際發生異常的位置)並從該幀中獲取模塊和 function 名稱。

該模塊很難獲得,但您可以擁有文件名和行號。 它們包含在您不需要自己格式化的 exc_info 中。 您可以將它們傳遞到日志 function 並使用格式化程序將其全部顯示。 這是一個示例代碼,可讓您了解如何完成此操作:

import sys
import logging
import traceback


def log_except_hook(*exc_info):
    logger = logging.getLogger(__name__)
    handler = logging.StreamHandler()
    handler.setFormatter(logging.Formatter('%(asctime)s %(fname)s:%(lnum)s %(message)s %(exc_info)s'))
    logger.addHandler(handler)

    frame = traceback.extract_tb(exc_info[2])[-1]
    fname = frame.filename
    lnum = frame.lineno
    logger.critical("Unhandled exception:", exc_info=exc_info, extra={'fname':fname, 'lnum':lnum})

sys.excepthook = log_except_hook

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM