在继承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!">
如果最简单的RequestHandler
是基类而不是子类logging.Handler
,那将是最简单的{{1}}(需要什么方法?)?
答案 0 :(得分:1)
查看Logger.log
的来源会将我带到Logger.callHandlers
,它仅在处理程序上调用handle
。因此,如果您将假处理程序直接注入到记录器实例中,那么这可能是您所需的最低要求。
如果您想与记录模块的其余部分真正实现保证兼容性,则唯一可以做的就是浏览该模块的源代码以了解其工作原理。 The documentation是一个很好的起点,但这并没有深入到内部。
如果您只是想为一个小用例编写一个虚拟处理程序,则可以跳过很多步骤而逃脱;尝试一下,看看失败的地方,并以此为基础。
否则,除了进入源代码之外,您别无选择(尽管尝试并查看中断)也是找到开始阅读的好方法)。
快速浏览the class' source会告诉我,该类中唯一的陷阱与模块对其对象的内部管理有关; Handler.__init__
将处理程序放入全局处理程序列表中,模块可以在任何地方使用该列表。但是除此之外,该类非常简单。应该不难阅读。
答案 1 :(得分:1)
通常,您可以通过使用包装函数覆盖__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
从上面的结果中可以看到,handle
和level
是基本日志记录处理程序唯一需要的属性。换句话说,@ jirassimok是正确的,因为handle
是Handler
类的唯一在外部调用的方法,但是也需要实现level
属性,因为它是也可以直接在Logger.callHandlers
方法中访问:
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!