# -*- coding:utf-8 -*- """ @Author : xuxingchen @Contact : xuxingchen@sinochem.com @Desc : 日志模块 """ import sys import io import time DEBUG = None LOGGER_PATH = None TOKEN_ERROR = "token无效" def log(text: str, log_path: str = None): """打印日志""" log_path = log_path if log_path else LOGGER_PATH log_line = '[{}] {}'.format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), text) if log_path: log_file = open(log_path, 'a', encoding='utf8') log_file.write("{}\n".format(log_line)) log_file.close() print(log_line) def log_plus(text: str, log_path: str = None, prefix_text: str = None, suffix_text: str = None): """加强版打印日志,预置了不同文字颜色""" log_path = log_path if log_path else LOGGER_PATH if prefix_text: log_line_start = f"[{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}] {prefix_text}" else: log_line_start = f"[{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}]" if suffix_text: log_line = f"{log_line_start} {text} {suffix_text}" else: log_line = f"{log_line_start} {text}" if log_path: log_file = open(log_path, 'a', encoding='utf8') log_file.write("{}\n".format(log_line)) log_file.close() print(log_line) def format_text(text_list: list, align_list: list = None) -> str: """格式化一些文本信息, 可以根据 align_list 调整每列文本的距离""" if not align_list: align_list = [(30, '<'), (60, '<')] formatted_text = [] for txt, (int_align, flag) in zip(text_list, align_list): formatted_text.append(f'{txt:{flag}{int_align}}') return ' '.join(formatted_text) def new_dc(msgs: str | float | int, fore_color: str = "", back_color: str = "") -> str: """给文本上色 fore_color格式如下: [{显示方式};{前景色};{背景色}m 显示方式 0(默认值)、1(高亮)、22(非粗体)、4(下划线)、24(非下划线)、 5(闪烁)、25(非闪烁)、7(反显)、27(非反显) 前景色 30(黑色)、31(红色)、32(绿色)、 33(黄色)、34(蓝色)、35(洋 红)、36(青色)、37(白色) 背景色 40(黑色)、41(红色)、42(绿色)、 43(黄色)、44(蓝色)、45(洋 红)、46(青色)、47(白色) 如: 高亮绿色红色背景 [1;32;41m 默认-绿字体 [32m """ if fore_color == "": fore_color = '[32m' # 默认绿色 return "\033{}{}{}\033[0m".format(back_color, fore_color, str(msgs)) def console_mute(func): """采用装饰器的方式提供函数的控制台标准输出临时置空,净化控制台环境""" def wrapper(*args, **kwargs): original_stdout = sys.stdout try: sys.stdout = io.StringIO() return func(*args, **kwargs) finally: # 恢复原始的 sys.stdout 和 sys.stderr sys.stdout = original_stdout return wrapper def log_speed_ms(start_time: float, suffix: str = "", prefix: str = "", number_color: str = "", decimal: int = 4): """控制台打印消耗的毫秒时间""" log(f"{suffix}用时:{new_dc(str(round((time.time() - start_time) * 1000, decimal)), number_color)}ms{prefix}") def speed_ms(start_time: float, decimal: int = 4): """消耗的毫秒时间""" return round((time.time() - start_time) * 1000, decimal) class Logger: """对控制台日志输出的二次封装,对部分常用日志进行预置""" @staticmethod def debug(text: str, log_path: str = None): """预置的debug形式的log""" log_path = log_path if log_path else LOGGER_PATH if isinstance(DEBUG, bool) and DEBUG: log_plus(text, log_path, f"[{new_dc('INFO-DEBUG', '[34m')}]") @staticmethod def info(text: str, log_path: str = None): """预置的info形式的log""" log_path = log_path if log_path else LOGGER_PATH log_plus(text, log_path, f"[{new_dc('INFO', '[34m')}]") @staticmethod def error(text: str, log_path: str = None): """预置的error形式的log""" log_path = log_path if log_path else LOGGER_PATH log_plus(text, log_path, f"[{new_dc('ERROR', '[1;31m')}]") @staticmethod def warn(text: str, log_path: str = None): """预置的warn形式的log""" log_path = log_path if log_path else LOGGER_PATH log_plus(text, log_path, f"[{new_dc('WARN', '[1;33m')}]") @staticmethod def init(text: str, log_path: str = None): """预置的error形式的log""" log_path = log_path if log_path else LOGGER_PATH log_plus(text, log_path, f"[{new_dc('INIT', '[35m')}]") @staticmethod def title(text: str, log_path: str = None): """预置title形式的显目log""" log_path = log_path if log_path else LOGGER_PATH log_plus(new_dc(text, '[1m'), log_path, "🚀", "🚀") @staticmethod def complete(text: str, log_path: str = None): """预置complete形式的显目log""" log_path = log_path if log_path else LOGGER_PATH log_plus(new_dc(text, '[1;32m'), log_path, "✅", "✅") @staticmethod def remove(text: str, log_path: str = None): """预置remove形式的显目log""" log_path = log_path if log_path else LOGGER_PATH log_plus(new_dc(text, '[1m'), log_path, "🚮", "🚮") @staticmethod def connect(text: str, log_path: str = None): """预置connect形式的显目log""" log_path = log_path if log_path else LOGGER_PATH log_plus(new_dc(text, '[1;32m'), log_path, "🔗", "🔗") @staticmethod def disconnect(text: str, log_path: str = None): """预置disconnect形式的显目log""" log_path = log_path if log_path else LOGGER_PATH log_plus(new_dc(text, '[1m'), log_path, "🚫", "🚫")