Python 自定义日志输出

news2025/4/17 0:47:33

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

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

日志类型可自定义

首先定义 Log基类 :LogRecord


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

#对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

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

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

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


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)


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

    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()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1632663.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

道路积水检查与报警

文章目录 模型训练积水图像数据集yolo训练流程 图像采集图像预处理模型训练参数设置积水检测与分类数据存储界面制作 模型训练 积水图像数据集 收集积水图像,制作数据集。每张图像对应的标注信息,通常包括目标的类别、边界框坐标等。标注数据可以通过标…

SAP的生成式AI

这是一篇openSAP中关于SAP生成式AI课程的笔记,原地址https://open.sap.com/courses/genai1/ 文章目录 Unit 1: Approaches to artificial intelligence概念三种范式监督学习非监督学习强化学习 Unit 2: Introduction to generative AI生成式AI基础模型关系基础模型有…

软件物料清单(SBOM)生成指南 .pdf

如今软件安全攻击技术手段不断升级,攻击数量显著增长。尤其是针对软件供应链的安全攻击,具有高隐秘性、追溯难的特点,对企业软件安全威胁极大。 同时,软件本身也在不断地更新迭代,软件内部成分安全性在持续变化浮动。…

报错:测试报错postman(测试接口)

报错如下 c.e.exception.GlobalExceptionHandler : 异常信息: Content type multipart/form-data;boundary--------------------------952399813172082093419475;charsetUTF-8 not supported 解决: 异常信息 Content type multipart/form-data;boundary…

STM32使用PWM控制舵机

系列文章目录 STM32单片机系列专栏 C语言术语和结构总结专栏 文章目录 1. 舵机简介 2. 硬件连接 3. 代码实现 3.1 PWM.c 3.2 PWM.h 3.3 Servo.c 3.4 Servo.h 3.5 main.c 3.6 完整工程文件 PWM和OC输出详解: STM32定时器的OC比较和PWM​​​​​​​ 1. …

树莓派学习笔记--树莓派终端基本操作与系统备份(全卡备份,压缩备份)

树莓派终端基本操作 sudo su #切换为超级用户身份 su lyh #切换回普通用户lyh(用户名)#目录切换命令 pwd #显示当前所在目录 cd ~ #切换到主目录(/home/用户名),~也可省略不写 cd dir …

python程序设计语言超详细知识总结

Python 首先 python 并不是简单,什么语言都有基础和高级之分,要想掌握一门语言,必须把高级部分掌握才行。 HelloWorld helloWorld.py print(hello, world)数据类型与变量 变量的数据类型数据类型描述变量的定义方式整数型 (int)整数&…

OpenVINO安装教程 Docker版

从 Docker 映像安装IntelDistribution OpenVINO™ 工具套件 本指南介绍了如何使用预构建的 Docker 镜像/手动创建镜像来安装 OpenVINO™ Runtime。 Docker Base 映像支持的主机操作系统: Linux操作系统 Windows (WSL2) macOS(仅限 CPU exectuion) 您可以使用预…

微软最新季度业绩结果充分说明了云和AI的增长、谷歌和AWS的竞争

微软最新的季度业绩超出了华尔街的各种预期,但对其服务合作伙伴来说,最重要的是这家科技巨头的预期:人工智能不仅能够增长,而且其云产品尚未达到稳定状态——人工智能是云的潜在增长加速器。 周五的一份分析师报告称,…

实现堆的各种基本运算的算法(数据结构)

以小堆为例,大堆就举一反三了。 堆的物理结构就是普通的数组,但是逻辑结构看成了一颗完全二叉树。 小堆,就是树的每一个父节点都小于他的孩子节点。如图中第一排的a与b。大堆,就是树的每一个父节点都大于他的孩子节点。如图中第…

Mysql基础(三)DDL之create table语句

一 create table 创表 说明: create table相关语句从功能上进行讲解补充: 前面已经讲解过相关的约束,已进行相关的铺垫声明: 参考价值较少,了解即可 ① 基本语法 思考: 约束加在哪里? ② 创建新表 强调:使…

node环境创建Vue项目

node环境创建Vue项目 目录 node环境创建Vue项目安装node.js安装Vue创建Vue项目 安装node.js 【1】.官网下载 【2】.选择路径 【3】配置环境变量 后面就是一路next完成安装 【4】测试 cmd输入node指令,显示版本号证明安装成功 安装Vue 【1】安装cnpm 这是由淘宝…

8.SysTick定时器

SysTick为系统滴答定时器 定时器分类 内核级定时器(系统滴答定时器) 延时定时中断(给系统提供时钟节拍)给操作系统提供时基(任务调度)FreeRTOS UCOS5ms 基本定时器 延时定时中断时间片(实现两盏LED灯同时以一个不同速度闪烁,轮询…

超越GPT-4,清华发布网页导航智能体AutoWebGLM

随着大语言模型(LLMs)的发展,Agent在网络导航等任务中展现出了前所未有的能力。想象一下,一个基于LLM的Agent能够在你享用早餐时为你总结在线新闻,这样的场景已经不再遥不可及。这种将LLMs融入日常任务的做法&#xff…

1Panel - 现代化、开源的 Linux 服务器运维管理面板

产品介绍 1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。 1Panel的官方网站:https://1panel.cn 1Panel的GitHub仓库:https://github.com/1Panel-dev/1Panel 体验环境:https://demo.1panel.cn 1Panel 特点 开源特性 Star 数…

LLaMA 3:大模型之战的新序幕

作者 | 符尧 OneFlow编译 翻译|杨婷、宛子琳、张雪聃 本文要点概览: 文本数据的扩展可能已经达到了极限,因为易于获取的网络文本资源(如Common Crawl、GitHub、ArXiv等)已基本被充分利用。 尽管如此,通过更…

JAVASE->数据结构|顺序表底层逻辑

✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:再无B~U~G-CSDN博客 目标: 1. 什么是 List 2. List 常见接口介绍 3. …

js 中的非空断言操作符 (!.)叹号加点

js 中的非空断言操作符 (!.)叹号加点 在 TypeScript 或 JavaScript 中,!.并不是一个官方的语法结构。然而,!符号在 TypeScript 中确实有特定的用法,它被称为非空断言操作符。 !通常用作逻辑非操作符,用于…

cuda和cudnn的安装(ubuntu22.04环境)

一、安装准备 安装依赖 sudo apt-get update sudo apt-get install g sudo apt-get install gcc sudo apt-get install make禁用默认驱动 sudo gedit /etc/modprobe.d/blacklist.conf 在末尾加上 blacklist nouveau options nouveau modeset0更新一下initramfs -u的镜像 s…

自动驾驶横向控制算法

本文内容来源是B站——忠厚老实的老王,侵删。 三个坐标系和一些有关的物理量 使用 frenet坐标系可以实现将车辆纵向控制和横向控制解耦,将其分开控制。使用右手系来进行学习。 一些有关物理量的基本概念: 运动学方程 建立微分方程 主要是弄…