Python 自定义日志输出

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 = Truethread.start()#设置日志输出根目录,保存的日志文件目录数-多出的会被删除def set_log_path(self, path, remain_count=7):self._log_path = pathself._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:continuequeue = 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:passself.is_deleted = Truetry: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):returndirs = [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 osclass LogOperateBase:cur_process_id = -1_default_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Logs")_log_helper = LogHelper()@staticmethoddef init_log(id, path="", remain_count=7):LogOperateBase.cur_process_id = idif not path:path = LogOperateBase._default_pathLogOperateBase._log_helper.set_path(path, remain_count)@staticmethoddef save():LogOperateBase._log_helper.save()

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


import traceback
from Modules.Tools.Logs import LogHelper,LogType
from Modules.Tools.LogOperateBase import LogOperateBaseclass LogOperate(LogOperateBase):@staticmethoddef debug(content):if __debug__:LogOperateBase._log_helper.record(LogType.Debug, content)@staticmethoddef info(message):LogOperateBase._log_helper.record(LogType.Info, message)@staticmethoddef web(message):LogOperateBase._log_helper.record(LogType.Web, message)@staticmethoddef start(message):LogOperateBase._log_helper.record(logt=LogType.Start,content= f"【{LogOperateBase.cur_process_id}】{message}")@staticmethoddef error_msg(message):LogOperateBase._log_helper.record(LogType.Error, message)@staticmethoddef 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@staticmethoddef send_log(message):LogOperateBase._log_helper.record(LogType.Send, message)@staticmethoddef click_log(message):LogOperateBase._log_helper.record(LogType.Click, message)@staticmethoddef 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.mzph.cn/pingmian/4831.shtml

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

相关文章

TDengine高可用架构之TDengine+Keepalived

之前在《TDengine高可用探讨》提到过,TDengine通过多副本和多节点能够保证数据库集群的高可用。单对于应用端来说,如果使用原生连接方式(taosc)还好,当一个节点下线,应用不会受到影响;但如果使用…

Python爬虫--Scrapy框架安装

Scrapy框架安装 , Scrapy 是 Python 领域专业的爬虫开发框架,已经完成爬虫程序的大部分通用工具 它使用了 Twisted 异步网络库来处理网络通讯。整体架构大致如下 第一步:挂小灰机或者将要安装的文件下载到本地 Scrapy 框架安装踩坑中 为什…

Blender曲线操作

1.几种常见建模方式 -多边形建模:Blender,C4D,3DsMax,MaYa -曲线: -曲面:Rhino(Nurbs) -雕刻:Blender,ZBrush -蜡笔:Blender 1)新…

【办公类-22-14】周计划系列(5-6)“周计划-06 19周的周计划教案合并打印PDF(最终打印版))

背景需求: 花了十周,终于把周计划教案的文字都写满、加粗、节日替换了。为了便于打印,我把19周的周计划教案全部合并在一起PDF。制作打印用PDF 思路 1、周计划是单独打印一张,因此要在第2页插入空白页, 2、教案有3页…

鸿蒙launcher浅析

鸿蒙launcher浅析 鸿蒙launcher源码下载鸿蒙launcher模块launcher和普通的应用ui展示的区别 鸿蒙launcher源码下载 下载地址如下: https://gitee.com/openharmony/applications_launcher 鸿蒙launcher模块 下载页面已经有相关文件结构的介绍了 使用鸿蒙编辑器D…

CMDB系统的目标

CMDB即配置管理数据库(Configuration Management Database, CMDB)系统被广泛应用于实现IT资产管理和IT服务管理。CMDB系统的目标是建立一个全面的、精确的信息数据库,用于追踪、管理和记录IT基础设施的配置信息及其相关关系,从而提…

OpenHarmony开发实例:【电话簿联系人Contacts】

样例简介 Contacts应用是基于OpenHarmony SDK开发的安装在润和HiSpark Taurus AI Camera(Hi3516d)开发板标准系统上的应用;应用主要功能是展示联系人列表,并点击某一列弹出联系人详细信息; 运行效果 样例原理 样例主要有一个list组件和dia…

Docker本地部署overleaf后,挖掘用户加密逻辑

overleaf的用户信息,保存在mongo数据库的users集合中。 用户密码则存在hashedPassword字段中 从开源的代码services\web\app\src\Features\Authentication\AuthenticationManager.js第303行可以找到密码加密逻辑。 本地可以通过下面的代码生成overleaf用户密码信息…

如何在每天特定的时间打开指定的网页?教你设置每天自动打开指定网页

在现代社会,互联网已成为我们日常生活和工作中不可或缺的一部分。随着科技的 发展,我们可以利用各种工具和技术来提高我们的工作效率和生活品质。其中,定 时自动打开指定的网址便是一个实用的功能,它可以帮助我们节省时间&#xf…

百万人都在求的网络安全学习路线,渗透漏洞防御总结(附图)

前言 不折腾的网络安全,和咸鱼有什么区别 目录 二、 前言三 、同源策略 3.1 什么是同源策略 3.2 为什么需要同源策略四 、XSS 4.1 概览 4.2 介绍 4.3 防御五 、CSRF 5.1 概览 5.2 介绍 5.3 防御六、 SQL 注入七 、流量劫持 7.1 DNS 劫持 7.2 HTTP 劫持…

【Canvas与艺术】 绘制五星红旗

【注意】 该图中五星定位和大小都是按 https://www.douyin.com/note/7149362345016380710 精确绘制的。 【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8&q…

【前端】6. JavaScript(WebAPI)

WebAPI 背景知识 什么是 WebAPI 前面学习的 JS 分成三个大的部分 ECMAScript: 基础语法部分DOM API: 操作页面结构BOM API: 操作浏览器 WebAPI 就包含了 DOM BOM. 这个是 W3C 组织规定的. (和制定 ECMAScript 标准的大佬们不是一伙人). 前面学的 JS 基础语法主要学的是 EC…

【多维动态规划】Leetcode 64. 最小路径和【中等】

最小路径和 给定一个包含非负整数的 m x n 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。 说明&#xff1a;每次只能向下或者向右移动一步。 示例 1&#xff1a; 输入&#xff1a;grid [[1,3,1],[1,5,1],[4,2,1]] 输出…

手动在Ubuntu22.04上部署LAMP环境

简介 LAMP环境是常用的Web开发环境之一&#xff0c;其中LAMP分别代表Linux、Apache、MySQL和PHP。本文介绍如何在Ubuntu操作系统的ECS实例内部署LAMP环境。 准备工作 该实例必须满足以下条件&#xff1a; 实例已分配公网IP地址或绑定弹性公网IP&#xff08;EIP&#xff09;。…

关于Dockerfile镜像实例

文章目录 Dockerfile镜像实例一、构建SSH镜像1、建立工作目录2、生成镜像3、启动容器并修改root密码 二、构建systemd镜像1、建立工作目录2、生成镜像3、运行镜像容器4、测试容器systemd 三、构建Nginx镜像1、建立工作目录2、编写Dockerfile脚本3、编写run.sh启动脚本4、生成镜…

源代码加密

企业到底该如何正确选择源代码加密产品&#xff1f; 源代码加密的方法和重点到底是怎样的&#xff1f; 源代码开发环境复杂&#xff0c;涉及的开发软件、文件类型庞杂多变&#xff0c;究竟有什么源代码加密软件能够适应众多开发软件而不影响原有的工作效率&#xff1f; 相信…

个人学习总结__打开摄像头、播放网络视频的以及ffmpeg推流

前言 最近入手了一款非常便宜的usb摄像头&#xff08;买回来感觉画质很低&#xff0c;没有描述的4k&#xff0c;不过也够用于学习了&#xff09;,想着利用它来开启流媒体相关技术的学习。第一步便是打开摄像头&#xff0c;从而才能够对它进行一系列后续操作&#xff0c;诸如实…

有趣的 CSS 图标整合技术!sprites精灵图,css贴图定位

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合…

vue3.0(三) Vite文件目录结构及SFC语法

文章目录 Vite介绍Vite文件目录结构SFC语法SFC 语法定义bug解决 Vite介绍 为什么使用Vite&#xff1f; 表现 与Vite的ESbuild预绑定使其比使用任何其他JS绑定器都快10到100倍。这是因为它有助于提高页面速度并将CommonJS/UMD模块转换为ESM。 基于Vite文件&#xff0c;“预绑定…

深入理解Linux调试工具eBPF和strace、内存泄漏处理、Kubernetes容器调试以及C++协程的崩溃信息收集

在软件开发领域&#xff0c;无论是初级开发者还是资深工程师&#xff0c;都需要面对复杂的调试工作。本文将介绍几个重要的调试工具和技术&#xff0c;并提供实际调试方法的指导&#xff0c;包括Linux环境下的eBPF和strace&#xff0c;内存泄漏问题的处理&#xff0c;Kubernete…