我想为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
我尝试了以下代码:
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")
我得到的是以下内容:
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
我怎样才能解决这个问题 - 最好是优雅的?不要犹豫,为我的其余代码提供建议。
答案 0 :(得分:3)
您的解决方案无效,因为当您致电'%(asctime)s - %(name)s - %(levelname)s - {0} - %(message)s'.format(log_status)
时,会创建一个新字符串并将其传递给Formatter
,而log_status
永远不会再使用。您需要一个自定义Formatter
来动态创建格式字符串。
但是看看这个问题是如何在Python官方文档中解决的:Logging Cookbook: Adding contextual information to your logging output - 请参阅自定义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')
输出:
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
...
答案 1 :(得分:0)
扩展 Messa's answer,您可以更改 ContextFilter
类实例的属性,而该更改将影响输出。对于您的示例代码如下:
import logging
class ContextFilter(logging.Filter):
def __init__(self):
super().__init__()
self._log_status = ""
def set_status(self, status: str):
self._log_status = status
def filter(self, record: logging.LogRecord) -> bool:
record.log_status = self._log_status
return True
# 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)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(log_status)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# Now we need to add filters to handlers
f = ContextFilter()
f.set_status("First Part")
fh.addFilter(f)
ch.addFilter(f)
logger.addHandler(fh)
logger.addHandler(ch)
# First part of the program
logger.info("One log message")
# Second part of the program
f.set_status("Second Part")
logger.info("Another log message")
这段代码给出了你想要的确切输出:
2021-01-16 20:49:18,848 - MyProgram - INFO - First Part - One log message
2021-01-16 20:49:18,848 - MyProgram - INFO - Second Part - Another log message