如何打电话logging.setLogRecordFactory在Python2中?

2024-06-13 10:21:03 发布

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

举个简单的例子:

import logging

class SmartLogRecord(logging.LogRecord):
    """ Dummy LogRecord example """

    def getMessage(self):
        return self.msg % self.args

logging.setLogRecordFactory(SmartLogRecord)

var = 'SmartLogRecord'
logging.warning('I am a %s', var)

我可以在Python 3上运行它并使用我的自定义LogRecord类,但是Python 2抛出一个错误:

^{pr2}$

Tags: importselfreturnexamplevarloggingdefargs
1条回答
网友
1楼 · 发布于 2024-06-13 10:21:03

以下是CPython 3.7中的setLogRecordFactory()及其所有荣耀:

# https://github.com/python/cpython/blob/29500737d45cbca9604d9ce845fb2acc3f531401/Lib/logging/__init__.py#L386
_logRecordFactory = LogRecord

def setLogRecordFactory(factory):
    global _logRecordFactory
    _logRecordFactory = factory

def getLogRecordFactory():
    return _logRecordFactory

def makeLogRecord(dict):
    rv = _logRecordFactory(None, None, "", 0, "", (), None, None)
    rv.__dict__.update(dict)
    return rv

Logger.makeRecord()中调用此函数:

^{pr2}$

相反,在Python 2中,这不是一件事:

^{3}$

您可以做的基本上是替换Logger对象上的.makeRecord()绑定方法。换句话说:

>>> class A:
...     def f(self, a, b):
...         return a + b

>>> def new_f(self, a, b):
...     return a * b
... 
>>> A.f = new_f
>>> A().f(10, 20)
200

这看起来像:

class MyLogRecord(logging.LogRecord):
    pass
    # override stuff here

def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None):
        print "Using a MyLogRecord instance"
        rv = MyLogRecord(name, level, fn, lno, msg, args, exc_info, func)
        if extra is not None:
            for key in extra:
                if (key in ["message", "asctime"]) or (key in rv.__dict__):
                    raise KeyError("Attempt to overwrite %r in LogRecord" % key)
                rv.__dict__[key] = extra[key]
        return rv

logging.Logger.makeRecord = makeRecord

插图:

>>> logging.error("hello")
Using a MyLogRecord instance
ERROR:root:hello

在本例中,您只是根据使用单个其他MyLogRecord类的特定需要对其进行裁剪。如果您真的愿意,您可以编写自己的setLogRecordFactory(),然后在替换的.makeRecord()方法中使用_logRecordFactory,就像Python3所做的那样。在


假设/备选方案(子类,不替换)

还有一个注释:这一切都假设您想要影响在别处创建的非“您自己的”实例。如果您只想影响您自己的代码定义的记录器,您可以只使用子类Logger,而不是完全替换属于logging.__init__模块名称空间的Logger类。在

相关问题 更多 >