0%

python | 开源的 logger 代码

这个是我在一个项目中见的开源代码。挺好用的。


目录结构


  • project
    • logger
      • log.py
    • service
      • test.py

log.py


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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import os
import sys
import traceback
import logging
import logging.handlers


class ColoredFormatter(logging.Formatter):

def __init__(self, fmt=None, datefmt=None):
logging.Formatter.__init__(self, fmt, datefmt)

def format(self, record):
# Color escape string
COLOR_RED = '\033[1;31m'
COLOR_GREEN = '\033[1;32m'
COLOR_YELLOW = '\033[1;33m'
COLOR_BLUE = '\033[1;34m'
COLOR_PURPLE = '\033[1;35m'
COLOR_CYAN = '\033[1;36m'
COLOR_GRAY = '\033[1;37m'
COLOR_WHITE = '\033[1;38m'
COLOR_RESET = '\033[1;0m'
# Define log color
LOG_COLORS = {
'DEBUG': '%s',
'INFO': COLOR_GREEN + '%s' + COLOR_RESET,
'WARNING': COLOR_YELLOW + '%s' + COLOR_RESET,
'ERROR': COLOR_RED + '%s' + COLOR_RESET,
'CRITICAL': COLOR_RED + '%s' + COLOR_RESET,
'EXCEPTION': COLOR_RED + '%s' + COLOR_RESET,
}
level_name = record.levelname
msg = logging.Formatter.format(self, record)
return LOG_COLORS.get(level_name, '%s') % msg


class Log(object):
def __init__(self, loggername='', filename=None, mode='a',
cmdlevel='DEBUG',
filelevel='INFO',
cmdfmt='[%(asctime)s] %(filename)s line:%(lineno)d %(levelname)-8s%(message)s',
filefmt='[%(asctime)s] %(levelname)-8s%(message)s',
cmddatefmt='%H:%M:%S',
filedatefmt='%Y-%m-%d %H:%M:%S',
backup_count=0, limit=20480, when=None, colorful=False):
self.filename = filename
self.loggername = loggername
if self.filename is None:
self.filename = getattr(sys.modules['__main__'], '__file__', 'log.py')
self.filename = os.path.basename(self.filename.replace('.py', '.log'))
# self.filename = os.path.join('/tmp', self.filename)
if not os.path.exists(os.path.abspath(os.path.dirname(self.filename))):
os.makedirs(os.path.abspath(os.path.dirname(self.filename)))
self.mode = mode
self.cmdlevel = cmdlevel
self.filelevel = filelevel
if isinstance(self.cmdlevel, str):
self.cmdlevel = getattr(logging, self.cmdlevel.upper(), logging.DEBUG)
if isinstance(self.filelevel, str):
self.filelevel = getattr(logging, self.filelevel.upper(), logging.DEBUG)
self.filefmt = filefmt
self.cmdfmt = cmdfmt
self.filedatefmt = filedatefmt
self.cmddatefmt = cmddatefmt
self.backup_count = backup_count
self.limit = limit
self.when = when
self.colorful = colorful
self.logger = None
self.streamhandler = None
self.filehandler = None
if self.cmdlevel > 10:
self.filefmt = '[%(asctime)s] %(levelname)-8s%(message)s'
self.cmdfmt = '[%(asctime)s] %(levelname)-8s%(message)s'
self.cmddatefmt = '%Y-%m-%d %H:%M:%S'
self.set_logger(cmdlevel=self.cmdlevel)

def init_logger(self):
if self.logger is None:
self.logger = logging.getLogger(self.loggername)
else:
logging.shutdown()
self.logger.handlers = []
self.streamhandler = None
self.filehandler = None
self.logger.setLevel(logging.DEBUG)

def add_streamhandler(self):
self.streamhandler = logging.StreamHandler()
self.streamhandler.setLevel(self.cmdlevel)
if self.colorful:
formatter = ColoredFormatter(self.cmdfmt, self.cmddatefmt)
else:
formatter = logging.Formatter(self.cmdfmt, self.cmddatefmt, )
self.streamhandler.setFormatter(formatter)
self.logger.addHandler(self.streamhandler)

def add_filehandler(self):
# Choose the filehandler based on the passed arguments
if self.backup_count == 0: # Use FileHandler
self.filehandler = logging.FileHandler(self.filename, self.mode)
elif self.when is None: # Use RotatingFileHandler
self.filehandler = logging.handlers.RotatingFileHandler(self.filename,
self.mode, self.limit, self.backup_count)
else: # Use TimedRotatingFileHandler
self.filehandler = logging.handlers.TimedRotatingFileHandler(self.filename,
self.when, 1, self.backup_count)
self.filehandler.setLevel(self.filelevel)
formatter = logging.Formatter(self.filefmt, self.filedatefmt, )
self.filehandler.setFormatter(formatter)
self.logger.addHandler(self.filehandler)

def set_logger(self, **kwargs):
keys = ['mode', 'cmdlevel', 'filelevel', 'filefmt', 'cmdfmt', \
'filedatefmt', 'cmddatefmt', 'backup_count', 'limit', \
'when', 'colorful']
for (key, value) in kwargs.items():
if not (key in keys):
return False
setattr(self, key, value)
if isinstance(self.cmdlevel, str):
self.cmdlevel = getattr(logging, self.cmdlevel.upper(), logging.DEBUG)
if isinstance(self.filelevel, str):
self.filelevel = getattr(logging, self.filelevel.upper(), logging.DEBUG)
if not "cmdfmt" in kwargs:
self.filefmt = '[%(asctime)s] %(filename)s line:%(lineno)d %(levelname)-8s%(message)s'
self.filedatefmt = '%Y-%m-%d %H:%M:%S'
self.cmdfmt = '[%(asctime)s] %(filename)s line:%(lineno)d %(levelname)-8s%(message)s'
self.cmddatefmt = '%H:%M:%S'
if self.cmdlevel > 10:
self.filefmt = '[%(asctime)s] %(levelname)-8s%(message)s'
self.cmdfmt = '[%(asctime)s] %(levelname)-8s%(message)s'
self.cmddatefmt = '%Y-%m-%d %H:%M:%S'
self.init_logger()
self.add_streamhandler()
self.add_filehandler()
# Import the common log functions for convenient
self.import_log_funcs()
return True

def addFileLog(self, log):
self.logger.addHandler(log.filehandler)
return self

def import_log_funcs(self):
log_funcs = ['debug', 'info', 'warning', 'error', 'critical',
'exception']
for func_name in log_funcs:
func = getattr(self.logger, func_name)
setattr(self, func_name, func)

def trace(self):
info = sys.exc_info()
for file, lineno, function, text in traceback.extract_tb(info[2]):
self.error('%s line:%s in %s:%s' % (file, lineno, function, text))
self.error('%s: %s' % info[:2])


logger = Log(cmdlevel='info', filename='logs/log_eos_voter.log', backup_count=1, when='D', colorful=True)

test.py


1
2
3
from logger.log import logger as log

log.info(***)
请我喝杯咖啡吧~