print#
纯print输出#
通过sys.stdout/sys.stderr重定向输出至文件
</>
python
1import sys
2class Tee:
3 """同时重定向 stdout 和 stderr 到文件和终端"""
4 def __init__(self, filename):
5 self.file = open(filename, 'a') # 追加模式
6 self.stdout = sys.stdout
7 self.stderr = sys.stderr
8
9 def write(self, message):
10 self.file.write(message)
11 self.stdout.write(message) # 标准输出到终端
12 self.file.flush() # 确保实时写入文件
13
14 def flush(self):
15 self.file.flush()
16
17# 脚本日志重定向
18sys.stdout = Tee(f"{__file__.split('.')[0]}.log")
19sys.stderr = Tee(f"{__file__.split('.')[0]}.log")封装print,自定义输出#
</>
python
1from datetime import datetime
2class Logger:
3 def now(self):return datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
4 def info(self, msg):print(self.now() + ' - INFO - ' + msg)
5 def warning(self, msg):print(self.now() + ' - WARN - ' + msg)
6 def error(self, msg):print(self.now() + ' - ERROR - ' + msg)
7
8logger = Logger()logging#
通用代码#
</>
python
1import logging
2import os
3from datetime import datetime
4
5def setup_logger(name, log_level=logging.INFO, log_file_path=None):
6 logger = logging.getLogger(name)
7 logger.setLevel(log_level)
8 formatter = logging.Formatter(
9 '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
10 datefmt='%Y-%m-%d %H:%M:%S'
11 )
12 console_handler = logging.StreamHandler()
13 console_handler.setFormatter(formatter)
14 logger.addHandler(console_handler)
15
16 if log_file_path is None:
17 return logger
18
19 file_handler = logging.FileHandler(log_file_path)
20
21 file_handler.setFormatter(formatter)
22 logger.addHandler(file_handler)
23 return logger默认logger再封装#
不设置formatter,自定义logging的info/debug/error方法
实现:
- info/debug日志分离
- 日志格式自定义
- 日期时间格式精确到.3f
- 增加marker功能
- 日志输出代码行准确指向前一个调用栈(调用封装日志模块的代码行)
- 自定义error日志上报、处理
- 日志锁(增加性能开销,低性能场景适用)
</>
python
1import logging
2import os, inspect
3from os.path import join
4from datetime import datetime
5def get_logger(log_root, infolog="info.log", debuglog="debug.log"):
6 if not os.path.exists(log_root):os.makedirs(log_root)
7 debuglogpath = join(log_root, debuglog)
8 infologpath = join(log_root, infolog)
9 list(map(lambda p:(os.remove(p) if os.path.exists(p) else None), [debuglogpath, infologpath]))
10 logger = logging.getLogger('my_logger')
11 logger.setLevel(logging.DEBUG)
12
13 # debug文件日志
14 debug_file_handler = logging.FileHandler(debuglogpath)
15 debug_file_handler.setLevel(logging.DEBUG)
16 logger.addHandler(debug_file_handler)
17
18 # info文件日志
19 info_file_handler = logging.FileHandler(infologpath)
20 info_file_handler.setLevel(logging.INFO)
21 logger.addHandler(info_file_handler)
22
23 # info终端日志
24 console_handler = logging.StreamHandler()
25 console_handler.setLevel(logging.INFO)
26 logger.addHandler(console_handler)
27
28 return logger
29
30class Logger:
31 def __init__(self):
32 self.logger = None
33 self.lock = threading.Lock()
34 self.marklength = 110
35 self.error_msg = []
36
37 def init_logger(self, infolog, debuglog, logroot):
38 self.logger = get_logger(logroot, infolog, debuglog)
39
40 def padding_size(self, msg):
41 return self.marklength - sum(map(lambda c:2 if ord(c) > 255 else 1, msg))
42
43 def now(self):
44 return datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
45
46 def debug(self, msg:str, frame=None):
47 frame = inspect.currentframe().f_back if not frame else frame
48 f = (frame.f_code.co_filename).split(os.sep)[-1].replace(".py", "")
49 l = frame.f_lineno
50 with self.lock:
51 self.logger.debug(self.now() + ' - DEBUG - ' + f'{f}-{l} - ' + str(msg))
52
53 def info(self, msg:str, frame=None, mark=None):
54 frame = inspect.currentframe().f_back if not frame else frame
55 f = (frame.f_code.co_filename).split(os.sep)[-1].replace(".py", "")
56 l = frame.f_lineno
57 markstr = ((self.padding_size(str(msg)) - len(f'{f}{l}')) * "-" + f"[{mark}]") if mark else ""
58 with self.lock:
59 self.logger.info(self.now() + ' - INFO - ' + f'{f}-{l} - ' + str(msg) + markstr)
60
61 def warning(self, msg:str, frame=None, mark=None):
62 frame = inspect.currentframe().f_back if not frame else frame
63 f = (frame.f_code.co_filename).split(os.sep)[-1].replace(".py", "")
64 l = frame.f_lineno
65 markstr = ((self.padding_size(str(msg)) - len(f'{f}{l}')) * "-" + f"[{mark}]") if mark else ""
66 with self.lock:
67 self.logger.warning(self.now() + ' - WARN - ' + f'{f}-{l} - ' + str(msg) + markstr)
68
69 def error(self, msg:str, frame=None, mark=None, report_msg=True):
70 frame = inspect.currentframe().f_back if not frame else frame
71 f = (frame.f_code.co_filename).split(os.sep)[-1].replace(".py", "")
72 l = frame.f_lineno
73 markstr = ((self.padding_size(str(msg)) - len(f'{f}{l}') - 1) * "-" + f"[{mark}]") if mark else ""
74 with self.lock:
75 self.logger.error(self.now() + ' - ERROR - ' + f'{f}-{l} - ' + str(msg) + markstr)
76 if report_msg:
77 self.error_msg.append(str(msg))自定义logger类,实现logger实例解耦#
使用自定义初始化函数init_logger,可以实现不同python文件使用不同logger实例
- 使用logging对象
</>
python
1class Logger:
2 def init_logger(self, logger):
3 self.logger = logger
4
5logger.init_logger(get_logger(logroot, infolog, debuglog))- 使用print封装
</>
python
1from datetime import datetime
2class Wrapprint:
3 def now(self):return datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
4 def info(self, msg):print(self.now() + ' - INFO - ' + msg)
5 def warning(self, msg):print(self.now() + ' - WARN - ' + msg)
6 def error(self, msg):print(self.now() + ' - ERROR - ' + msg)
7
8class Logger:
9 def init_logger(self, logger):
10 self.logger = logger
11
12logger.init_logger(Wrapprint())