eventlet模块中select出现ValueError错误
eventlet.monkey_patch是否影响threading

python自定义windowsr日志支持文件分割

妙音 posted @ 2021年1月20日 13:48 in python , 1210 阅读

描述

 
python自带的RotatingFileHandler,在windows中运行, 分割文件rename时会出问题。因为windows不支持rename正在使用的文件
 

解决办法

 
自定义handler, 按大小和日期切割文件
 
原理: handler写文件时调用emit, 其中shouldRollover判断是否要分割, doRollover进行分割. 重写这个两个函数就可以
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class BaseRotatingHandler(logging.FileHandler):
 
    def emit(self, record):
        """
        Emit a record.
 
        Output the record to the file, catering for rollover as described
        in doRollover().
        """
        try:
            if self.shouldRollover(record):
                self.doRollover()
            logging.FileHandler.emit(self, record)
        except Exception:
            self.handleError(record)
 

示例

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import os
import time
import datetime
import logging
from logging.handlers import RotatingFileHandler
from pathlib import Path
 
 
class AutumnRotatingFileHandler(RotatingFileHandler):
    """
    日志+大小+支持windows
    """
 
    def __init__(self, filename, mode='a', maxBytes=0, backupCount=99, encoding=None, delay=False, backupDayCount=30):
        filename = str(filename)
        self.date_format = "%Y%m%d"
        self.create_date = self._now_date()
        self.backupCount = backupCount
 
        # 保存原始文件名
        self.filename = str(Path(filename).absolute())
        self.backupDayCount = backupDayCount
 
        RotatingFileHandler.__init__(self, self.last_file_name(filename), mode=mode, maxBytes=maxBytes, backupCount=backupCount, encoding=encoding, delay=delay)
 
    def _now_date(self):
        return time.strftime(self.date_format, time.localtime())
 
    def doRollover(self):
        """
        Do a rollover, as described in __init__().
        """
        # 关闭当前文件
        if self.stream:
            self.stream.close()
            self.stream = None
 
        # 生成最新文件名
        suffix = "."+ self._now_date()
        self.baseFilename = str(self.filename) + suffix
        if self.backupCount > 0:
            for i in range(0, self.backupCount):
                number_suffix = "{:0>2d}".format(i)
                sfn = ".".join([self.baseFilename, number_suffix])
                if os.path.exists(sfn):
                    continue
                else:
                    break
            number_suffix = "{:0>2d}".format(i)
            self.baseFilename = ".".join([self.baseFilename, number_suffix])
 
        # 删除过期文件
        self.deleteExpiredFiles()
 
        # 打开
        self.stream = self._open()
        self.create_date = self._now_date()
 
    def shouldRollover(self, record):
        """
        Determine if rollover should occur.
 
        Basically, see if the supplied record would cause the file to exceed
        the size limit we have.
        """
        # 文件分割条件1: 日期变化
        if self._now_date() != self.create_date:
            return 1
 
        if self.stream is None:                 # delay was set...
            self.stream = self._open()
 
        # 文件分割条件1: 文件大小超过限制
        if self.maxBytes > 0:                   # are we rolling over?
            msg = "%s\n" % self.format(record)
            self.stream.seek(0, 2#due to non-posix-compliant Windows feature
            if self.stream.tell() + len(msg) >= self.maxBytes:
                return 1
        return 0
 
    def deleteExpiredFiles(self):
        """
        删除过期文件
        """
        dead_datetime = datetime.datetime.now() - datetime.timedelta(days=self.backupDayCount)
 
        filenames = []
        for i in range(1, 3):
            date = dead_datetime - datetime.timedelta(days=1)
            date_str = date.strftime(self.date_format)
 
            base_name = "%s.%s" % (self.filename, date_str)
            filenames.append(base_name)
 
            for j in range(1, self.backupCount):
                sfn = "%s.%d" % (base_name, j)
                filenames.append(sfn)
 
        # delete file
        for filename in filenames:
            if os.path.exists(filename):
                try:
                    os.remove(sfn)
                except:
                    pass
 
    def last_file_name(self, filename):
        """
        文件名
        """
        suffix = "."+self._now_date()
        base_filename = str(filename) + suffix
        if self.backupCount > 0:
            for i in reversed(range(0, self.backupCount)):
                number_suffix = "{:0>2d}".format(i)
                sfn = ".".join([base_filename, number_suffix])
                # 最近存在的文件
                if os.path.exists(sfn):
                    break
                else:
                    continue
            number_suffix = "{:0>2d}".format(i)
            base_filename = ".".join([base_filename, number_suffix])
        return base_filename
 
Avatar_small
Darren 说:
2024年1月17日 15:34

https://m.goaloo88.com/
https://www.goaloo88.com/
Goaloo covers 2000+ soccer/football and basketball leagues, cups and tournaments (English Premier League/EPL, and UEFA Champions League, NBA etc.).

Avatar_small
Darren 说:
2024年1月17日 15:34

https://m.goaloo88.com/
https://www.goaloo88.com/
Goaloo covers 2000+ soccer/football and basketball leagues, cups and tournaments (English Premier League/EPL, and UEFA Champions League, NBA etc.).

Avatar_small
Simplethoughts - エキサ 说:
2024年11月09日 13:05

Don’t think. Thinking is the enemy of creativity. It’s self-conscious, and anything self-conscious is lousy.
You can’t try to do things. You simply must do things.” – Ray Bradbury

Avatar_small
Naikpharmacy 说:
2025年1月08日 12:03

<a href="https://naikpharmacy.in/">NaikPharmacy</a> is a great online platform for all your healthcare needs! The variety of products, fast delivery, and excellent customer service make it my go-to for medications and wellness items. Highly recommend!

Avatar_small
Naikpharmacy 说:
2025年1月08日 12:04

Naikpharmacy is a great online platform for all your healthcare needs! The variety of products, fast delivery, and excellent customer service make it my go-to for medications and wellness items. Highly recommend!

https://naikpharmacy.in/

Avatar_small
/awaisinternational 说:
2025年1月26日 22:25

Awais International offers a fantastic range of IT products, including high-quality desktop computers, gaming laptops, and gaming PCs. They provide some of the best gaming laptops on the market, ensuring top-notch performance and reliability for gamers and professionals alike. A one-stop shop for all your tech needs!

https://awaisinternational.com/


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter