Вот setLogRecordFactory()
в CPython 3.7 во всей его красе:
# 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
Где это вызывается в Called в Logger.makeRecord()
:
def makeRecord(self, name, level, fn, lno, msg, args, exc_info,
func=None, extra=None, sinfo=None):
"""
A factory method which can be overridden in subclasses to create
specialized LogRecords.
"""
rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func,
sinfo)
Наоборот, в Python 2 это не вещь:
# https://github.com/python/cpython/blob/7c2c01f02a1821298a62dd16ecc3a12da663e14b/Lib/logging/__init__.py#L1261
def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None):
"""
A factory method which can be overridden in subclasses to create
specialized LogRecords.
"""
rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func)
Что вы можете сделать, это в основном заменить .makeRecord()
связанный метод на Logger
объекте. Другими словами:
>>> 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()
, как показано выше, а затем использовать _logRecordFactory
в своем методе замены .makeRecord()
, как это делает Python 3.
Предположение / альтернативы (подкласс, не заменяйте)
Еще один комментарий: все это предполагает, что вы хотите повлиять на logger
экземпляров, которые не являются "вашими", которые были созданы в другом месте. Если вы только хотите повлиять на регистраторы, которые определяет ваш собственный код, вы можете просто подкласс Logger
вместо полной замены класса Logger
, который принадлежит пространству имен модуля logging.__init__
.