Как каждый день писать логи в новый файл Python?
Есть скрипт. Он пишет логи сейчас в один файл. Мне нужно,чтобы по дате разносились логи и хранились 7 дней. Нужно хранить в архиве за 7 дней файлы, просто в папке лежали 7 файлов за каждый день.. а после 2х недели старый архив удалялся и архивировалась уже след неделя? Вот конфигурация logging.conf
[loggers]
keys=root
[handlers]
keys=consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(asctime)s - %(process)s - %(threadName)-10s - %(name)s - %(levelname)s - %(message)s
datefmt=
Вот как записываю логи в скрипте:
fileHandler = logging.FileHandler('./logfile.log')
fileHandler.setFormatter(logging.Formatter(fmt='%(asctime)s - %(process)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(fileHandler)
Ответы (1 шт):
Можно использовать TimedRotatingFileHandler (https://docs.python.org/3.8/library/logging.handlers.html#timedrotatingfilehandler). Если ничего не напутал, то код использования в Вашем случае будет примерно такой:
from logging.handlers import TimedRotatingFileHandler
filename = 'logfile.log'
handler = TimedRotatingFileHandler(filename, when="midnight", interval=1, backupCount=7)
handler.suffix = "%Y-%m-%d"
logger.addHandler(handler)
when отвечает за интервалы записи лога,backupCount за количество хранимых файлов.
Теперь, если нужно хранить архивы. Набросал подобный хэндлер:
import os
import zipfile
from logging.handlers import TimedRotatingFileHandler
class ZipTimedRotatingFileHandler(TimedRotatingFileHandler):
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None):
super().__init__(filename, when, interval, backupCount, encoding, delay, utc, atTime)
def make_zip(self):
dir_path, base_filename = os.path.split(self.baseFilename)
logs_list = [f for f in os.listdir(dir_path)
if all([f.startswith(base_filename), f != base_filename, not f.endswith('.zip')])]
if len(logs_list) >= self.backupCount:
with zipfile.ZipFile('archive_{}.zip'.format(logs_list[0]), 'w') as zip_file:
for f in logs_list:
file = os.path.join(dir_path, f)
zip_file.write(file, os.path.base_filename(file), compress_type=zipfile.ZIP_DEFLATED)
os.remove(file)
def doRollover(self):
if self.backupCount > 0:
self.make_zip()
super().doRollover()
def getFilesToDelete(self):
return []
За основу взял используемый выше TimedRotatingFileHandler, от которого наследую ZipTimedRotatingFileHandler.
В doRollover() мы вызываем новый метод make_zip(), который архивирует логи, когда их число превышает хранимый объем из backupCount. После мы вызываем doRollover() от предка TimedRotatingFileHandler, который у нас осуществляет ротацию имен логов.
Ниже пример использования для посекундного сохранения логов:
import time
from logging import getLogger, INFO, shutdown
filename = 'logfile.log'
logger = getLogger('time_test')
logger.setLevel(INFO)
handler = ZipTimedRotatingFileHandler(filename, when="S", interval=1, backupCount=3)
handler.suffix = "%Y-%m-%d_%S-%M-%H"
logger.addHandler(handler)
for _ in range(10):
logger.info('Hello')
time.sleep(2)
shutdown()
Update:
Вернул обратно в хэндлер getFilesToDelete(), поскольку в super().doRollover() будет вызываться именно он, а не наследуемый getFilesToDelete(). Нужно для сокращения кода. Подчистка файлов у нас идет в make_zip, что приводит к тому, что в наследуемом getFilesToDelete() будет выполняться лишний код, отвечающий за подготовку списка для удаления файлов в TimedRotatingFileHandler.doRollover(), который ни к чему не приведет — мы уже все удалили и в архив поместили.