动态调整日志格式

ald*_*ado 3 python logging

我想为 python 程序创建一个记录器,它在程序运行期间更改其格式。这是必要的,因为我希望记录器除了日志消息之外还显示有关当前正在运行的程序部分的信息。我想要的是这样的(程序的不同部分 - 第一部分、第二部分应该被记录):

2016-11-15 21:09:07,042 - MyProgram - INFO - First Part - One log message
2016-11-15 21:09:07,042 - MyProgram - INFO - Second Part - Another log message
Run Code Online (Sandbox Code Playgroud)

我尝试了以下代码:

import logging

#Set up logger
logfile = str('example.log')
logger = logging.getLogger('MyProgram')
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler(logfile)
fh.setLevel(logging.INFO)

ch = logging.StreamHandler()
ch.setLevel(logging.INFO)

log_status = 'First Part'
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - {0} - %(message)s'.format(log_status))

fh.setFormatter(formatter)
ch.setFormatter(formatter)


logger.addHandler(fh)
logger.addHandler(ch)

#First part of the program
logger.info("One log message")

#Second part of the program
log_status = 'Second Part'

logger.info("Another log message")
Run Code Online (Sandbox Code Playgroud)

但我得到的是以下内容:

2016-11-15 21:09:07,042 - MyProgram - INFO - First Part - One log message
2016-11-15 21:09:07,042 - MyProgram - INFO - First Part - Another log message
Run Code Online (Sandbox Code Playgroud)

我怎样才能解决这个问题——最多可以优雅地解决?请随时为我的其余代码提供建议。

Mes*_*ssa 6

您的解决方案不起作用,因为当您调用 时'%(asctime)s - %(name)s - %(levelname)s - {0} - %(message)s'.format(log_status),会创建一个新字符串并将其传递给Formatter并且log_status永远不会再次使用。您需要一个Formatter动态创建格式字符串的自定义。

但是请参阅 Python 官方文档中如何解决此问题:Logging Cookbook:将上下文信息添加到日志输出- 请参阅自定义的示例logging.Filter

import logging
from random import choice

class ContextFilter(logging.Filter):
    """
    This is a filter which injects contextual information into the log.

    Rather than use actual contextual information, we just use random
    data in this demo.
    """

    USERS = ['jim', 'fred', 'sheila']
    IPS = ['123.231.231.123', '127.0.0.1', '192.168.0.1']

    def filter(self, record):

        record.ip = choice(ContextFilter.IPS)
        record.user = choice(ContextFilter.USERS)
        return True

if __name__ == '__main__':
    levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL)
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s')
    a1 = logging.getLogger('a.b.c')
    a2 = logging.getLogger('d.e.f')

    f = ContextFilter()
    a1.addFilter(f)
    a2.addFilter(f)
    a1.debug('A debug message')
    a1.info('An info message with %s', 'some parameters')
    for x in range(10):
        lvl = choice(levels)
        lvlname = logging.getLevelName(lvl)
        a2.log(lvl, 'A message at %s level with %d %s', lvlname, 2, 'parameters')
Run Code Online (Sandbox Code Playgroud)

输出:

2010-09-06 22:38:15,292 a.b.c DEBUG    IP: 123.231.231.123 User: fred     A debug message
2010-09-06 22:38:15,300 a.b.c INFO     IP: 192.168.0.1     User: sheila   An info message with some parameters
2010-09-06 22:38:15,300 d.e.f CRITICAL IP: 127.0.0.1       User: sheila   A message at CRITICAL level with 2 parameters
2010-09-06 22:38:15,300 d.e.f ERROR    IP: 127.0.0.1       User: jim      A message at ERROR level with 2 parameters
...
Run Code Online (Sandbox Code Playgroud)