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()
相关推荐
朝朝辞暮i8 分钟前
VLA 系统学习第 20 课——Diffusion Policy 为什么要先给动作加噪,再学习把噪声去掉?
人工智能·python·深度学习·transformer·vla
全栈弄潮儿24 分钟前
Python实战第3期:输入输出与字符串操作
python·agent
goehou36 分钟前
MCP 传输方式实战:stdio、Streamable HTTP、WebSocket 该选哪个
python·llm·agent·教程·mcp
用户0332126663671 小时前
如何快速拆分超大 Excel 文件【Python 教程】
python·excel
kimnoic1 小时前
Python中使用封装类还是函数以及它们的区别
开发语言·python
青柠之夏cc1 小时前
Python Java PHP底层对比:内存并发性能全解析
开发语言·python·线程
TomEval1 小时前
【测AI】第10篇:AI 模型功能测试实战 —— 测试用例怎么设计?
人工智能·python·功能测试·测试用例
半亩码田1 小时前
C#转Python第5.1篇:异步编程:asyncio vs async/await,语法相似但机制不同
开发语言·python·c#
yi0111 小时前
DAY27: LeetCode 110. 平衡二叉树 | 在递归中判断是否平衡
人工智能·笔记·python·算法·leetcode·二叉树·递归
言乐62 小时前
PythonLOLM自动生成复盘报告模型
开发语言·前端·数据库·人工智能·python