1 #!/usr/local/python/bin
2 # coding=utf-8
3
4 '''Implements a simple log library.
5
6 This module is a simple encapsulation of logging module to provide a more
7 convenient interface to write log. The log will both print to stdout and
8 write to log file. It provides a more flexible way to set the log actions,
9 and also very simple. See examples showed below:
10
11 Example 1: Use default settings
12
13 import log
14
15 log.debug('hello, world')
16 log.info('hello, world')
17 log.error('hello, world')
18 log.critical('hello, world')
19
20 Result:
21 Print all log messages to file, and only print log whose level is greater
22 than ERROR to stdout. The log file is located in '/tmp/xxx.log' if the module
23 name is xxx.py. The default log file handler is size-rotated, if the log
24 file's size is greater than 20M, then it will be rotated.
25
26 Example 2: Use set_logger to change settings
27
28 # Change limit size in bytes of default rotating action
29 log.set_logger(limit = 10240) # 10M
30
31 # Use time-rotated file handler, each day has a different log file, see
32 # logging.handlers.TimedRotatingFileHandler for more help about 'when'
33 log.set_logger(when = 'D', limit = 1)
34
35 # Use normal file handler (not rotated)
36 log.set_logger(backup_count = 0)
37
38 # File log level set to INFO, and stdout log level set to DEBUG
39 log.set_logger(level = 'DEBUG:INFO')
40
41 # Both log level set to INFO
42 log.set_logger(level = 'INFO')
43
44 # Change default log file name and log mode
45 log.set_logger(filename = 'yyy.log', mode = 'w')
46
47 # Change default log formatter
48 log.set_logger(fmt = '[%(levelname)s] %(message)s'
49 '''
50
51 __author__ =
"tuantuan.lv <dangoakachan@foxmail.com>"
52 __status__ =
"Development"
53
54 __all__ = [
'set_logger',
'debug',
'info',
'warning',
'error',
55 'critical',
'exception']
56
57 import os
58 import sys
59 import logging
60 import logging.handlers
61
62 # Color escape string
63 COLOR_RED=
'\033[1;31m'
64 COLOR_GREEN=
'\033[1;32m'
65 COLOR_YELLOW=
'\033[1;33m'
66 COLOR_BLUE=
'\033[1;34m'
67 COLOR_PURPLE=
'\033[1;35m'
68 COLOR_CYAN=
'\033[1;36m'
69 COLOR_GRAY=
'\033[1;37m'
70 COLOR_WHITE=
'\033[1;38m'
71 COLOR_RESET=
'\033[1;0m'
72
73 # Define log color
74 LOG_COLORS =
{
75 'DEBUG':
'%s',
76 'INFO': COLOR_GREEN +
'%s' +
COLOR_RESET,
77 'WARNING': COLOR_YELLOW +
'%s' +
COLOR_RESET,
78 'ERROR': COLOR_RED +
'%s' +
COLOR_RESET,
79 'CRITICAL': COLOR_RED +
'%s' +
COLOR_RESET,
80 'EXCEPTION': COLOR_RED +
'%s' +
COLOR_RESET,
81 }
82
83 # Global logger
84 g_logger =
None
85
86 class ColoredFormatter(logging.Formatter):
87 '''A colorful formatter.'''
88
89 def __init__(self, fmt = None, datefmt =
None):
90 logging.Formatter.
__init__(self, fmt, datefmt)
91
92 def format(self, record):
93 level_name =
record.levelname
94 msg =
logging.Formatter.format(self, record)
95
96 return LOG_COLORS.get(level_name,
'%s') %
msg
97
98 def add_handler(cls, level, fmt, colorful, **
kwargs):
99 '''Add a configured handler to the global logger.'''
100 global g_logger
101
102 if isinstance(level, str):
103 level =
getattr(logging, level.upper(), logging.DEBUG)
104
105 handler = cls(**
kwargs)
106 handler.setLevel(level)
107
108 if colorful:
109 formatter =
ColoredFormatter(fmt)
110 else:
111 formatter =
logging.Formatter(fmt)
112
113 handler.setFormatter(formatter)
114 g_logger.addHandler(handler)
115
116 return handler
117
118 def add_streamhandler(level, fmt):
119 '''Add a stream handler to the global logger.'''
120 return add_handler(logging.StreamHandler, level, fmt, True)
121
122 def add_filehandler(level, fmt, filename , mode, backup_count, limit, when):
123 '''Add a file handler to the global logger.'''
124 kwargs =
{}
125
126 # If the filename is not set, use the default filename
127 if filename
is None:
128 filename = getattr(sys.modules[
'__main__'],
'__file__',
'log.py')
129 filename = os.path.basename(filename.replace(
'.py',
'.log'))
130 filename = os.path.join(
'/tmp', filename)
131
132 kwargs[
'filename'] =
filename
133
134 # Choose the filehandler based on the passed arguments
135 if backup_count == 0:
# Use FileHandler
136 cls =
logging.FileHandler
137 kwargs[
'mode' ] =
mode
138 elif when
is None:
# Use RotatingFileHandler
139 cls =
logging.handlers.RotatingFileHandler
140 kwargs[
'maxBytes'] =
limit
141 kwargs[
'backupCount'] =
backup_count
142 kwargs[
'mode' ] =
mode
143 else:
# Use TimedRotatingFileHandler
144 cls =
logging.handlers.TimedRotatingFileHandler
145 kwargs[
'when'] =
when
146 kwargs[
'interval'] =
limit
147 kwargs[
'backupCount'] =
backup_count
148
149 return add_handler(cls, level, fmt, False, **
kwargs)
150
151 def init_logger():
152 '''Reload the global logger.'''
153 global g_logger
154
155 if g_logger
is None:
156 g_logger =
logging.getLogger()
157 else:
158 logging.shutdown()
159 g_logger.handlers =
[]
160
161 g_logger.setLevel(logging.DEBUG)
162
163 def set_logger(filename = None, mode =
'a', level=
'ERROR:DEBUG',
164 fmt =
'[%(levelname)s] %(asctime)s %(message)s',
165 backup_count = 5, limit = 20480, when =
None):
166 '''Configure the global logger.'''
167 level = level.split(
':')
168
169 if len(level) == 1:
# Both set to the same level
170 s_level = f_level =
level[0]
171 else:
172 s_level = level[0]
# StreamHandler log level
173 f_level = level[1]
# FileHandler log level
174
175 init_logger()
176 add_streamhandler(s_level, fmt)
177 add_filehandler(f_level, fmt, filename, mode, backup_count, limit, when)
178
179 # Import the common log functions for convenient
180 import_log_funcs()
181
182 def import_log_funcs():
183 '''Import the common log functions from the global logger to the module.'''
184 global g_logger
185
186 curr_mod = sys.modules[
__name__]
187 log_funcs = [
'debug',
'info',
'warning',
'error',
'critical',
188 'exception']
189
190 for func_name
in log_funcs:
191 func =
getattr(g_logger, func_name)
192 setattr(curr_mod, func_name, func)
193
194 # Set a default logger
195 set_logger()
原文地址:https://www.oschina.net/code/snippet_813668_14236