我想使用日志记录模块在Python循环的每次迭代中生成一个新的日志文件。我正在分析for循环中的数据,其中循环的每个迭代都包含有关新对象的信息。我想为每个对象生成一个日志文件。
我查看了日志记录模块的文档,并且能够按时间间隔或在日志文件填满时更改日志文件,但是我看不到如何迭代生成具有新名称的新日志文件。我提前知道循环中有多少个对象。
我想象的伪代码是:
import logging
for target in targets:
logfile_name = f"{target}.log"
logging.basicConfig(format='%(asctime)s - %(levelname)s : %(message)s',
datefmt='%Y-%m/%dT%H:%M:%S',
filename=logfile_name,
level=logging.DEBUG)
# analyse target infomation
logging.info('log target info...')
但是,日志记录信息总是附加到目标1的第一日志文件中。
是否有一种方法可以在每个循环开始时强制使用新的日志文件?
答案 0 :(得分:1)
这可能不是最佳解决方案,但是它将为每次迭代创建新的日志文件。这是在每次迭代中添加一个新的文件处理程序。
import logging
targets = ["a", "b", "c"]
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
for target in targets:
log_file = "{}.log".format(target)
log_format = "|%(levelname)s| : [%(filename)s]--[%(funcName)s] : %(message)s"
formatter = logging.Formatter(log_format)
# create file handler and set the formatter
file_handler = logging.FileHandler(log_file)
file_handler.setFormatter(formatter)
# add handler to the logger
logger.addHandler(file_handler)
# sample message
logger.info("Log file: {}".format(target))
答案 1 :(得分:1)
您需要使用记录器对象,而不是直接使用logging
。仔细阅读文档here。
在循环中的第一个语句中创建一个新的记录器对象。下面是一个可行的解决方案。
import logging
import sys
def my_custom_logger(logger_name, level=logging.DEBUG):
"""
Method to return a custom logger with the given name and level
"""
logger = logging.getLogger(logger_name)
logger.setLevel(level)
format_string = ("%(asctime)s — %(name)s — %(levelname)s — %(funcName)s:"
"%(lineno)d — %(message)s")
log_format = logging.Formatter(format_string)
# Creating and adding the console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(log_format)
logger.addHandler(console_handler)
# Creating and adding the file handler
file_handler = logging.FileHandler(logger_name, mode='a')
file_handler.setFormatter(log_format)
logger.addHandler(file_handler)
return logger
if __name__ == "__main__":
for item in range(10):
logger = my_custom_logger(f"Logger{item}")
logger.debug(item)
这会为每次迭代写入不同的日志文件。
答案 2 :(得分:1)
这不一定是最佳答案,但适用于我的情况,只想将其放在此处以供将来参考。我创建了一个如下所示的函数:
def logger(filename, level=None, format=None):
"""A wrapper to the logging python module
This module is useful for cases where we need to log in a for loop
different files. It also will allow more flexibility later on how the
logging format could evolve.
Parameters
----------
filename : str
Name of logfile.
level : str, optional
Level of logging messages, by default 'info'. Supported are: 'info'
and 'debug'.
format : str, optional
Format of logging messages, by default '%(message)s'.
Returns
-------
logger
A logger object.
"""
levels = {"info": logging.INFO, "debug": logging.DEBUG}
if level is None:
level = levels["info"]
else:
level = levels[level.lower()]
if format is None:
format = "%(message)s"
# https://stackoverflow.com/a/12158233/1995261
for handler in logging.root.handlers[:]:
logging.root.removeHandler(handler)
logger = logging.basicConfig(filename=filename, level=level, format=format)
return logger
如您所见(您可能需要向下滚动上面的代码以查看return logger
行),我正在使用logging.basicConfig()
。程序包中包含所有用于记录内容的模块,这些文件的开头均包含以下内容:
import logging
import other stuff
logger = logging.getLogger()
class SomeClass(object):
def some_method(self):
logger.info("Whatever")
.... stuff
做循环时,我这样称呼事情:
if __name__ == "__main__":
for i in range(1, 11, 1):
directory = "_{}".format(i)
if not os.path.exists(directory):
os.makedirs(directory)
filename = directory + "/training.log"
logger(filename=filename)
我希望这会有所帮助。
答案 3 :(得分:0)
这是此问题的有效版本。我只有在目标进入循环之前已经具有.log的情况下才能使它工作,因此您可能要在进入目标之前再添加一个目标,并使用.log扩展名覆盖所有目标
import logging
targets = ["a.log","b.log","c.log"]
for target in targets:
log = logging.getLogger(target)
formatter = logging.Formatter('%(asctime)s - %(levelname)s : %(message)s', datefmt='%Y-%m/%dT%H:%M:%S')
fileHandler = logging.FileHandler(target, mode='a')
fileHandler.setFormatter(formatter)
streamHandler = logging.StreamHandler()
streamHandler.setFormatter(formatter)
log.addHandler(fileHandler)
log.addHandler(streamHandler)
log.info('log target info...')