[英]Write header to a python log file, but only if a record gets written
fh = logging.FileHandler('example.log',delay = True)
fh.setLevel(logging.INFO)
Since delay is True, the file will never be written unless something is logged. 由于延迟为True,除非记录某些内容,否则永远不会写入文件。 At that point, the first line in the file is the first record, and it will contain the asctime, levelname etc elements
此时,文件中的第一行是第一个记录,它将包含asctime,levelname等元素
Using python 2.7.10, is there a sane way to add a line (or two) the first time a record is written that don't include those elements? 使用python 2.7.10,是否有一种理智的方法来在第一次写入不包含这些元素的记录时添加一行(或两行)?
I can just write to the file before using it for logging, but if I do that, I end up with logs empty but for the header. 我可以在使用它进行日志记录之前写入该文件,但如果我这样做,我最终会将日志留空但是标题。
The desired output might look like: 所需的输出可能如下所示:
Using test.fil with option 7
2015-11-01 13:57:58,045 :log_example: INFO fn:main result:process 4 complete --7 knights said ni
2015-11-01 13:57:58,045 :log_example: INFO fn:main result:process 3 complete --3 bunnies attacked
Thanks, 谢谢,
Sub class the FileHandler to create your own custom FileHandleWithHeader as shown below: 子类FileHandler创建自己的自定义FileHandleWithHeader,如下所示:
import os
import logging
# Create a class that extends the FileHandler class from logging.FileHandler
class FileHandlerWithHeader(logging.FileHandler):
# Pass the file name and header string to the constructor.
def __init__(self, filename, header, mode='a', encoding=None, delay=0):
# Store the header information.
self.header = header
# Determine if the file pre-exists
self.file_pre_exists = os.path.exists(filename)
# Call the parent __init__
logging.FileHandler.__init__(self, filename, mode, encoding, delay)
# Write the header if delay is False and a file stream was created.
if not delay and self.stream is not None:
self.stream.write('%s\n' % header)
def emit(self, record):
# Create the file stream if not already created.
if self.stream is None:
self.stream = self._open()
# If the file pre_exists, it should already have a header.
# Else write the header to the file so that it is the first line.
if not self.file_pre_exists:
self.stream.write('%s\n' % self.header)
# Call the parent class emit function.
logging.FileHandler.emit(self, record)
# Create a logger and set the logging level.
logger = logging.getLogger("example")
logger.setLevel(logging.INFO)
# Create a file handler from our new FileHandlerWith Header class and set the
# logging level.
fh = FileHandlerWithHeader('example.log', 'This is my header', delay=True)
fh.setLevel(logging.INFO)
# Add formatter to the file handler.
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
fh.setFormatter(formatter)
# Add the handler to the logger.
logger.addHandler(fh)
# Since the constructor of the FileHandlerWithHeader was passed delay=True
# the file should not exist until the first log as long as the log file did
# not pre-exist.
print "Ready to write to the the example.log file."
raw_input("Press Enter to continue...")
# Send 3 logs to the logger.
logger.info("First line in the file")
logger.info("Second line in the file")
logger.info("Third line in the file")
# The log file should now be created and only have a header at the begining of
# the file.
print "The example.log file should exist and have a header."
This script should run as is in Python 2.7. 该脚本应该在Python 2.7中运行。 If the "example.log" file already exists, it will not recreate the header.
如果“example.log”文件已存在,则不会重新创建标头。
This solution required knowledge of the logging source code found here and general use of the python logging package found here . 日志源代码的该解决方案所需的知识发现这里和一般用途的Python记录包找到这里 。
I had a simpler idea. 我有一个更简单的想法。 The following just uses a custom formatter.
以下只使用自定义格式化程序。 The first message formatted spits out a header record then after that just does normal formatting.
格式化的第一条消息会抛出一个标题记录,之后只进行正常的格式化。
import logging
class FormatterWithHeader(logging.Formatter):
def __init__(self, header, fmt=None, datefmt=None, style='%'):
super().__init__(fmt, datefmt, style)
self.header = header # This is hard coded but you could make dynamic
# Override the normal format method
self.format = self.first_line_format
def first_line_format(self, record):
# First time in, switch back to the normal format function
self.format = super().format
return self.header + "\n" + self.format(record)
def test_logger():
logger = logging.getLogger("test")
logger.setLevel(logging.DEBUG)
formatter = FormatterWithHeader('First Line Only')
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(formatter)
logger.addHandler(ch)
logger.info("This line will kick out a header first.")
logger.info("This line will *not* kick out a header.")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.