没有子类的最基本的日志处理程序

2024-10-05 14:31:54 发布

您现在位置:Python中文网/ 问答频道 /正文

在子类化logging.Handler时,我可以通过执行以下操作来创建自定义处理程序:

import requests
import logging

class RequestsHandler(logging.Handler):
    def emit(self, record):
        res = requests.get('http://google.com')
        print (res, record)

handler = RequestsHandler()
logger = logging.getLogger(__name__)
logger.addHandler(handler)
logger.warning('ok!')
# <Response [200]> <LogRecord: __main__, 30, <stdin>, 1, "ok!">

如果它只是一个没有子类化logging.Handler的基类,那么最简单的RequestHandler(也就是说,它需要什么方法?)


Tags: importself处理程序loggingdefresoklogger
2条回答

查看Logger.log的源代码可以找到^{},它只调用处理程序上的handle。因此,如果您将假处理程序直接注入到记录器实例中,那么这可能是您所需要的最小值

如果您真的想保证与日志模块的其余部分兼容,那么您唯一能做的就是查看模块的源代码以了解它是如何工作的The documentation是一个很好的起点,但这并没有深入到内部

如果您只是尝试为一个小用例编写一个虚拟处理程序,那么您可以跳过很多步骤;尝试一些东西,看看哪里失败了,然后在此基础上再接再厉

否则,你就别无选择,只能深入到源代码中去(尽管尝试一些东西,看看有什么突破也可以是一个很好的方法来找到地方开始阅读)

快速浏览一下the class' source就知道类中唯一的gotchas与模块对其对象的内部管理有关Handler.__init__将处理程序放入全局处理程序列表中,模块可以在任意位置使用该列表。但除此之外,这门课非常简单;它不应该太难读

一般来说,您可以通过使用包装函数重写__getattribue__方法来找出类的哪些属性是从外部访问的 如果调用者的类与当前类不同,则将要访问的属性的名称添加到集合中:

import logging
import sys

class MyHandler(logging.Handler):
    def emit(self, record):
        pass

def show_attribute(self, name):
    caller_locals = sys._getframe(1).f_locals
    if ('self' not in caller_locals or
            object.__getattribute__(caller_locals['self'], '__class__') is not
            object.__getattribute__(self, '__class__')):
        attributes.add(name)
    return original_getattribute(self, name)
attributes = set()

original_getattribute = MyHandler.__getattribute__
MyHandler.__getattribute__ = show_attribute

以便:

handler = MyHandler()
logger = logging.getLogger(__name__)
logger.addHandler(handler)
logger.warning('ok!')    
print(attributes)

输出:

{'handle', 'level'}

演示:https://repl.it/@blhsing/UtterSoupyCollaborativesoftware

从上面的结果可以看出,handlelevel是基本日志处理程序所需的唯一属性。换句话说,@jirassimok是正确的,因为handleHandler类的唯一外部调用的方法,但是也需要实现level属性,因为它也可以在^{}方法中直接访问:

if record.levelno >= hdlr.level:

其中level属性必须是整数,如果要处理所有日志记录级别的记录,则应为0

因此,Handler类的最小实现应该类似于:

class MyHandler:
    def __init__(self):
        self.level = 0

    def handle(self, record):
        print(record.msg)

以便:

handler = MyHandler()
logger = logging.getLogger(__name__)
logger.addHandler(handler)
logger.warning('ok!')

输出:

ok!

相关问题 更多 >