Python 自定义日志输出

Python 有着内置的日志输出模块:logging 使用也很方便,但我们今天不说这个,我们用文件读写模块,实现自己的日志输出模块;这样在项目中,可以存在更高的自由度及更高的扩展性;

先来看看日志输出的文件效果:根目录 \Logs\ 按日期输出 \2024-04-28\ 按日志类型输出txt文件

日志类型可自定义

首先定义 Log基类 :LogRecord

python 复制代码
class LogRecord:
    #初始化日志模块
    def __init__(self):
        self._total_log_dic = {} #字典项用来保存 日志类型:日志内容
        self._log_path = os.path.join(os.getcwd(), "LogRecord") #日志输出路径
        self._locker = threading.Lock() #线程锁
        self.create_auto_save_thread() #创建自定运行的线程

    #创建自定运行的线程
    def create_auto_save_thread(self):
        def auto_save():
            while True:
                self.write_in_txt_once() #将缓存字典中的日志信息都输出到文件中
                threading.Event().wait(3)
        #定义线程运行auto_save方法
        thread = threading.Thread(target=auto_save)
        thread.daemon = True
        thread.start()

    #设置日志输出根目录,保存的日志文件目录数-多出的会被删除
    def set_log_path(self, path, remain_count=7):
        self._log_path = path
        self._remain_count = remain_count

    #添加日志信息到缓存字典中
    def record(self, logt, content):
        if logt not in self._total_log_dic:
            self._total_log_dic[logt] = deque()
        self._total_log_dic[logt].append(
            f"\r\n【{datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')}】:{content}")

    #将缓存字典中的数据,输出到日志文件中
    def write_in_txt_once(self):
        with self._locker:
            for item in self._total_log_dic:
                if len(self._total_log_dic[item]) == 0:
                    continue
                queue = self._total_log_dic[item]
                v_list = []
                while len(queue) > 0:
                    v_list.append(queue.popleft())
                if len(v_list) > 0:
                    self.write_in_txt(v_list, item)
    #写文件的操作方法
    def write_in_txt(self, logs, logs_name):
        if not hasattr(self, "is_deleted") or not self.is_deleted:
            try:
                self.delete_director(self._log_path, self._remain_count)
            except:
                pass
            self.is_deleted = True
        try:
            directory_name = datetime.now().strftime("%Y-%m-%d")
            log_path = os.path.join(self._log_path, directory_name)
            if not os.path.exists(log_path):
                os.makedirs(log_path)
            single_path = os.path.join(log_path, f"{logs_name}.txt")
            with open(single_path, "a", encoding="utf-8") as f:
                for line in logs:
                    f.write(line + "")
        except:
            pass
    #删除保存天数外的目录文件
    def delete_director(self, path, remain_count):
        if not os.path.exists(path):
            return
        dirs = [d for d in os.listdir(
            path) if os.path.isdir(os.path.join(path, d))]
        if len(dirs) > remain_count:
            for i in range(len(dirs) - remain_count):
                shutil.rmtree(os.path.join(path, dirs[i]))
    #强制触发将缓存字典中的数据写入到日志文件中
    def save(self):
        self.write_in_txt_once()

接下来对LogRecord基类进行一次的封装:LogHelper

python 复制代码
#对LogRecord基类进行一次的封装
class LogHelper:
    def __init__(self):
        self.log_helper = LogRecord()
    #初始化日志模块,输出根目录,保存天数等
    def set_path(self, path, remain_count=7):
        self.log_helper.set_log_path(path, remain_count)
    #添加日志记录到缓存字典
    def record(self, logt, content):
        self.log_helper.record(logt, content)
    #将缓存字典中的日志信息都输出到文件中
    def save(self):
        self.log_helper.save()

定义 日志类型:LogType

python 复制代码
#日志类型-也对应相应的文件名
class LogType:
    Send = "Send"
    Info = "Info"
    Error = "Error"
    Click = "Click"
    Start = "Start"
    Web = "Web"
    Debug = "Debug"

接下来就对在代码中使用的输出模块进行功能定义: LogOperateBase

python 复制代码
import os

class LogOperateBase:
    cur_process_id = -1
    _default_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Logs")
    _log_helper = LogHelper()

    @staticmethod
    def init_log(id, path="", remain_count=7):
        LogOperateBase.cur_process_id = id
        if not path:
            path = LogOperateBase._default_path
        LogOperateBase._log_helper.set_path(path, remain_count)

    @staticmethod
    def save():
        LogOperateBase._log_helper.save()

最后定义日志输出类,即代码中实际使用的对象:LogOperate

python 复制代码
import traceback
from Modules.Tools.Logs import LogHelper,LogType
from Modules.Tools.LogOperateBase import LogOperateBase

class LogOperate(LogOperateBase):
    @staticmethod
    def debug(content):
        if __debug__:
            LogOperateBase._log_helper.record(LogType.Debug, content)

    @staticmethod
    def info(message):
        LogOperateBase._log_helper.record(LogType.Info, message)

    @staticmethod
    def web(message):
        LogOperateBase._log_helper.record(LogType.Web, message)

    @staticmethod
    def start(message):
        LogOperateBase._log_helper.record(logt=LogType.Start,content= f"【{LogOperateBase.cur_process_id}】{message}")

    @staticmethod
    def error_msg(message):
        LogOperateBase._log_helper.record(LogType.Error, message)

    @staticmethod
    def error(message, ex):
        try:
            log = f"{message}\r\n{ex.__class__.__name__}{str(ex)}\r\n{traceback.format_exc()}\r\n-----------------------------------------------------------------------"
            LogOperateBase._log_helper.record(LogType.Error, log)
        except:
            pass

    @staticmethod
    def send_log(message):
        LogOperateBase._log_helper.record(LogType.Send, message)

    @staticmethod
    def click_log(message):
        LogOperateBase._log_helper.record(LogType.Click, message)

    @staticmethod
    def general(log_type, message):
        LogOperateBase._log_helper.record(log_type, message)

最后就能在代码中这样使用了:

python 复制代码
    LogOperate.init_log(os.getpid(),Config.log_path)
    
    LogOperate.start("开始启动程序")
    LogOperate.info("开始启动程序")
    LogOperate.web("开始启动程序")
    LogOperate.click_log("开始启动程序")
    LogOperate.debug("开始启动程序")
    LogOperate.error_msg("开始启动程序")
    LogOperate.send_log("开始启动程序")
    
    LogOperate.start("开始启动程序1")
    LogOperate.info("开始启动程序1")
    LogOperate.web("开始启动程序1")
    LogOperate.click_log("开始启动程序1")
    LogOperate.debug("开始启动程序1")
    LogOperate.error_msg("开始启动程序1")
    LogOperate.send_log("开始启动程序1")
    
    LogOperate.save()
相关推荐
smppbzyc19 分钟前
2025年亚太杯(中文赛项)数学建模B题【疾病的预测与大数据分析】原创论文讲解(含完整python代码)
python·数学建模·数据分析·数学建模竞赛·亚太杯数学建模·亚太杯
xiaocainiao88131 分钟前
Python 实战:构建可扩展的命令行插件引擎
开发语言·python
运器1232 小时前
【一起来学AI大模型】PyTorch DataLoader 实战指南
大数据·人工智能·pytorch·python·深度学习·ai·ai编程
音元系统2 小时前
Copilot 在 VS Code 中的免费替代方案
python·github·copilot
超龄超能程序猿2 小时前
(5)机器学习小白入门 YOLOv:数据需求与图像不足应对策略
人工智能·python·机器学习·numpy·pandas·scipy
cooldream20094 小时前
Python 包管理新时代:深入了解 `uv` 的使用与实践
python·uv·包管理器
之歆4 小时前
Python-魔术方法-创建、初始化与销毁-hash-bool-可视化-运算符重载-容器和大小-可调用对象-上下文管理-反射-描述器-二分-学习笔记
笔记·python·学习
胖达不服输4 小时前
「日拱一码」025 机器学习——评价指标
人工智能·python·机器学习·评价指标
brave_zhao5 小时前
JavaBeanUtils javaBean转map, 实体类转map,实体集合转List<Map>
linux·windows·python
apihz6 小时前
通用图片搜索-搜狗源免费API接口使用指南
android·java·python·php·音视频