4

我是 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)

我该怎么做才能让它自动旋转,贴上旋转日期或序列号,以进行识别。我不打算轮换其中的任何一个,只需保留数据的每日日志文件即可。(或者可能是每小时文件?)

4

3 回答 3

17

For anyone arriving via Google, please don't move the log file out from under the logger while it is in use by calling the system copy of move commands or etc.

What you are looking for is a 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')
于 2016-06-08T14:19:22.770 回答
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)

“日志文件”是文件的名称。我已经将旧日志复制了一个新的日志文件,其名称基于时间和日期,然后清空了原始文件。如果你想每隔一小时轮换一次,把这个脚本放在 cron 中。

于 2013-09-29T08:47:44.623 回答
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您实际上可以控制何时创建新文件。每次应用于日期时间的模式创建日志消息时,都与先前应用的模式不同,将创建一个新文件。

于 2019-04-10T15:38:29.557 回答