需要使用Python进行每日日志轮换(0utc)

问题描述 投票:1回答:3

我是Python的入选者。我写了一个小记录器,从串口获取数据并将其写入日志文件。我有一个小程序打开文件追加,写,然后关闭。我怀疑这可能不是最好的方法,但这是我到目前为止所想到的。

我希望能够在00 UTC自动执行日志轮换,但到目前为止,我尝试使用RotatingFileHandler执行此操作失败了。

这是代码的样子:

import time, serial, logging, logging.handlers,os,sys
from datetime import *

CT12 = serial.Serial()
CT12.port = "/dev/ct12k"
CT12.baudrate = 2400
CT12.parity = 'E'
CT12.bytesize = 7
CT12.stopbits = 1
CT12.timeout = 3

logStart = datetime.now()
dtg = datetime.strftime(logStart, '%Y-%m-%d %H:%M:%S ')
ctlA = unichr(1)
bom = unichr(2)
eom = unichr(3)
bel = unichr(7)
CT12Name = [ctlA, 'CT12-NWC-test']
CT12Header = ['-Ceilometer Logfile \r\n', '-File created: ', dtg, '\r\n']

def write_ceilo ( text ) :
    f = open ('/data/CT12.log', 'a')
    f.write (text)
    f.close ()

write_ceilo(''.join(CT12Header))

CT12.open()

discard = CT12.readlines()
#print (discard)

while CT12.isOpen():
    response = CT12.readline()
    if len(response) >= 3:
        if response[0] == '\x02' :
            now=datetime.now()
            dtg=datetime.strftime(now, '-%Y-%m-%d %H:%M:%S\r\n')
            write_ceilo(dtg)
            write_ceilo(''.join(CT12Name))
            write_ceilo(response)

我该怎么做才能使其自动旋转,粘贴旋转日期或序列号,以便识别。我不打算将这些中的任何一个旋转出来,只保留数据的每日日志文件。 (或者可能是每小时的文件?)

python logging pyserial
3个回答
8
投票

对于通过Google抵达的任何人,请不要通过调用移动命令的系统副本等将日志文件从记录器下移出。

你在寻找什么是TimedRotatingFileHandler

import time

import logging
from logging.handlers import TimedRotatingFileHandler

# format the log entries
formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)s %(message)s')

handler = TimedRotatingFileHandler('/path/to/logfile.log', 
                                   when='midnight',
                                   backupCount=10)
handler.setFormatter(formatter)
logger = logging.getLogger(__name__)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

# generate example messages
for i in range(10000):
    time.sleep(1)
    logger.debug('debug message')
    logger.info('informational message')
    logger.warn('warning')
    logger.error('error message')
    logger.critical('critical failure')

0
投票

你可以这样做:

import os
import time
date1 = time.strftime('%Y%m%d%H%M%S')
cmd1= "cp logfile logfile{0}".format(date1)
cmd2= "cat /dev/null > logfile"
os.system(cmd1)
os.system(cmd2)

'logfile'是文件的名称。我已经将旧日志复制了一个新的日志文件,其名称基于时间和日期,然后清空原始文件。如果要每隔一小时旋转一次,请将此脚本放在cron中。


0
投票

对于那些不喜欢旋转文件的人,但只是想使用一个文件处理程序来立即写入名称中具有特定日期的文件:编写自己的处理程序并不困难。这是一个例子:

class FileHandlerWithOneFilePerPeriod(FileHandler):
"""A handler which writes formatted logging records to files, one file per period."""

def __init__(self, filename_pattern, mode='a', encoding=None, delay=False):
    """
    Constructs the file handler.

    :param filename_pattern: the filename. Use strftime() directives to specify the format of the period.
    For example, %Y%m%d can be used to generate one log file per day.
    :param mode: the mode to open the file before writing. Common values are 'w' for writing (truncating the file
    if it already exists), 'x' for creating and writing to a new file, and 'a' for appending (which on some Unix
    systems, means that all writes append to the end of the file regardless of the current seek position).
    :param encoding: encoding is the name of the encoding used to decode or encode the file. This should only be
    used in text mode.
    :param delay: True if the file is opened when the first log message is emitted; False if the file is opened now
    by the constructor.
    """
    self.filename_pattern = filename_pattern
    filename = datetime.now().strftime(self.filename_pattern)
    super().__init__(filename, mode, encoding, delay)

def emit(self, record: LogRecord):
    new_filename = datetime.fromtimestamp(record.created).strftime(self.filename_pattern)
    if self.stream is None:
        self.set_new_filename(new_filename)
    elif self.differs_from_current_filename(new_filename):
        self.close()
        self.set_new_filename(new_filename)

    super().emit(record)

def set_new_filename(self, new_filename):
    self.baseFilename = new_filename

def differs_from_current_filename(self, filename: str) -> bool:
    return filename != self.baseFilename

要使用此处理程序,请在字典中使用以下值进行配置(使用logging.config.dictConfig()

version: 1
formatters:
  simple:
    format: '%(asctime)s %(name)s %(levelname)s %(message)s'
handlers:
  console:
    class: logging.StreamHandler
    level: DEBUG
    formatter: simple
    stream: ext://sys.stdout
  file:
    class: my_package.my_module.FileHandlerWithOneFilePerPeriod
    level: DEBUG
    formatter: simple
    filename_pattern: my_logging-%Y%m%d.log
root:
  level: DEBUG
  handlers: [console, file]

这将记录到控制台和文件。每天使用一个文件。更改my_packagemy_module以匹配放置处理程序的模块。将my_logging更改为更合适的名称。

通过更改filename_pattern中的日期模式,您实际上可以控制何时创建新文件。每次应用于日期时间的模式创建日志消息与先前应用的模式不同时,将创建新文件。

© www.soinside.com 2019 - 2024. All rights reserved.