【问题标题】:Inherit python logger from parent function scope从父函数范围继承 python 记录器
【发布时间】:2022-09-27 17:36:06
【问题描述】:

我希望我的函数do_x 使用(子)记录器__main__.do_all,该记录器在调用do_x 的父范围do_all 中定义。相反,默认情况下使用根记录器。

有没有办法强制do_x 使用子记录器__main__.do_all?我是否应该将记录器作为参数传递给do_x,即使在许多帖子中都不推荐它?假设我也想使用其他(子)记录器从其他范围调用do_x

import logging

logging.basicConfig(format=\'%(asctime)s - %(name)s - %(funcName)s - %(levelname)s - %(message)s\')
logger = logging.getLogger(__name__)

def do_x():
    logger.warning(\'doing x\')

def do_all():
    logger = logging.getLogger(__name__ + \'.do_all\')
    logger.warning(\'Starting do_all\')
    do_x()

def do_all_other():
    logger = logging.getLogger(__name__ + \'.do_all_other\')
    logger.warning(\'Starting do_all_other\')
    do_x()

do_all()
do_all_other()

生产

2022-09-27 11:34:40,562 - __main__.do_all - do_all - WARNING - Starting do_all
2022-09-27 11:34:40,562 - __main__ - do_x - WARNING - doing x
2022-09-27 11:34:40,562 - __main__.do_all_other - do_all_other - WARNING - Starting do_all_other
2022-09-27 11:34:40,562 - __main__ - do_x - WARNING - doing x

我希望输出的第二行和最后一行分别使用__main__.do_all__main__.do_all_other

  • do_x() 需要知道从哪里调用它。只有两种方法:将父节点的名称作为参数传递,或者检查堆栈
  • 没有真正定义记录器功能。调用getLogger 返回(如果需要,创建)由logging 模块管理的特定记录器实例,无论在哪里调用getLogger

标签: python logging


【解决方案1】:
import logging
import inspect

logging.basicConfig(format='%(asctime)s - %(name)s - %(funcName)s - %(levelname)s - %(message)s')

def do_x():
    logger_name = __name__ + '.' + inspect.stack()[1].function
    logger = logging.getLogger(logger_name)
    logger.warning('some log')

def do_all():
    do_x()

def do_other():
    do_x()


do_all()
do_other()

生产

2022-09-26 17:33:06,967 - __main__.do_all - do_x - WARNING - some log
2022-09-26 17:33:06,967 - __main__.do_other - do_x - WARNING - some log

需要最新版本的 python,但也适用于旧版本。 inspect.stack() 只是在旧版本中以稍微不同的格式返回数据。

【讨论】:

    【解决方案2】:

    logger 命名空间独立于函数范围。 do_x 应该简单地对 getLogger 进行相同的调用以使用相同的 Logger 实例。

    def do_x():
        logging.getLogger(__name__ + '.do_all').info('doing x')
    

    【讨论】:

    • 它不能解决“使用其他记录器从其他范围调用do_x”的可能性。我稍微更新了这个问题来说明这个问题。将do_x 视为由各种父函数调用的通用函数。虽然感谢您的回答。
    • 如果您想要不同的输出,为什么要使用相同的记录器呢?
    • 我不想使用相同的记录器,实际上我想要完全相反。我希望do_x 中的logger 变量(它是变量吗?)可以指向函数父作用域中的Logger 实例,具体取决于调用do_x 的位置。同时,我想保持do_x 的代码足够通用,这样我就不必在每次使用新记录器添加新调用时对其进行编辑。假设do_x是一些简单的数据转换,我想在途中记录一些中间结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-23
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    • 2018-08-18
    • 1970-01-01
    相关资源
    最近更新 更多