logging | 项目开发中日志模块logging在整个工程中的应用

news2024/12/30 4:09:14

日志模块

  • 日志介绍
  • 1. logging使用场景
    • 设置级别
  • 2. 实际logging使用 - 学习版
    • 2.1 终端输出StreamHandler
    • 2.2 日志文件中输出FileHandler
    • 2.3 同时写入终端和文件
    • 2.4 .Formatter参数语句
  • 3. 封装logging模块 - 实战版 ⭐
    • 3.1 配置config文件夹下project_config.py文件
      • time模块
    • 3.2 封装util文件夹下logging_until.py文件
    • 3.3 其他模块下的mycode文件
    • 注意事项
      • 解决

日志介绍

一个合格的程序,日志是必须要输出的。 我们借助Python的logging库,来完成日志输出。先编写基础的日志模块代码,可供业务逻辑代码使用。

所说的日志就是程序在运行时,程序当前处于什么状态,通过对外输出信息来确定。对外输出的这个信息,就是程序的运行日志。`

在这里插入图片描述

  • 级别

CRITICAL =50
FATAL= CRITICAL
ERROR= 40
WARNING =30
WARN= WARNING
INFO= 20
DEBUG=10
NOTSET =0

1. logging使用场景

# 注意使用场景   每个类型的级别不同 
logging.debug('debug 日志输出')  # 罗嗦模式
logging.info("info日志输出")     # 代码关键点输出
logging.warning("warning日志输出")  # 可能出问题地方 警告输出
logging.error("error日志输出")      # 出问题
logging.fatal("fatal中志输出")  # 致命的  程序无法执行时

在这里插入图片描述
默认是warnging级别以上的输出信息

设置级别

import logging

logging.getLogger().setLevel(10) # 只会输出 大于等于该数值的 logging

# 注意使用场景
logging.debug('debug 日志输出')  # 罗嗦模式
logging.info("info日志输出")     # 代码关键点输出
logging.warning("warning日志输出")  # 可能出问题地方 警告输出
logging.error("error日志输出")      # 出问题
logging.fatal("fatal中志输出")  # 致命的  程序无法执行时

默认的warning级别是30,当设置为10的时候,所有的日志都可以看到 方便我们开发时使用
设置为30 则有些日志 不需要让用看到 产品简介 同时关键信息 是让开发人员获取

2. 实际logging使用 - 学习版

  • Pycharm目录结构
    在这里插入图片描述

在这里插入图片描述

2.1 终端输出StreamHandler

核心理解:

  1. 导入模块 (自己的文件名不要和内置模块名称重名,否则内置模块无法使用)
  2. 日志管理对象: 负责日志的收集工作
  3. 日志处理器: 负责日志的输出形式管理(终端/文件) 日志格式: 负责日志的输出格式管理
  4. 日志格式:
'%(asctime)s - [%(levelname)s] - %(filename)s[%(lineno)d]:%(message)s'
  • 设置logger对象 假设是logger.py
# 导包
import logging

##################### 日志器对象的创建和配置 #####################
# 1. 日志器对象的创建
logger = logging.getLogger()

# 2. 日志处理器的创建  输出到终端
stream_handler = logging.StreamHandler()

# 3. 将日志处理器绑定到日志器对象上
logger.addHandler(stream_handler)

# TODO: 4. 创建一个格式对象
fmt = logging.Formatter('%(asctime)s - [%(levelname)s] - %(filename)s[%(lineno)d]:%(message)s')

# TODO: 5. 将日志格式对象绑定到日志处理器上
stream_handler.setFormatter(fmt)
  • 在模块文件中引入 mycode.py
 ######################### 日志的输出 #######################
 # 1. 设置日志输出级别
 logger.setLevel(logging.INFO)  # INFO级别以上的输出
 # 2. 输出不同级别的日志信息
 logger.debug('这是一个debug级别的日志信息')
 logger.info('这是一个info级别的日志信息')
 logger.warning('这是一个warning级别的日志信息')
 logger.error('这是一个error级别的日志信息')
 logger.critical('这是一个critical级别的日志信息')

在这里插入图片描述

2.2 日志文件中输出FileHandler

  • logger.py 输出到文件
# 导入logging模块
import logging

#################### 日志器对象的创建和配置 ####################
# 1. 日志器对象的创建
logger = logging.getLogger()

# TODO: 2. 创建换一个文件类型的日志处理器
# 注意: filename要传入一个log文件的路径,可以使用绝对路径也可以使用相对路径,但是文件目录一定要存在,文件可以不存在
# 举例: ../logs/test.log 路径中 logs目录必须存在, test.log可以不存在
file_handler = logging.FileHandler(
    filename='../logs/test.log',
    mode='a',
    encoding='utf8'
)
# 3. 将日志处理器绑定到日志器对象上
logger.addHandler(file_handler)
# 4. 创建一个格式对象
fmt = logging.Formatter('%(asctime)s - [%(levelname)s] - %(filename)s[%(lineno)d]:%(message)s')
# 5. 将日志格式对象绑定到日志处理器上
file_handler.setFormatter(fmt)
  • mycode.py
######################### 日志的输出 #######################
# 1. 设置日志输出级别
logger.setLevel(logging.INFO)
# 2. 输出不同级别的日志信息
logger.debug('这是一个debug级别的日志信息')
logger.info('这是一个info级别的日志信息')
logger.warning('这是一个warning级别的日志信息')
logger.error('这是一个error级别的日志信息')
logger.critical('这是一个critical级别的日志信息')

提前创建好该文件filename=‘…/logs/test.log’

2.3 同时写入终端和文件

file_handler logging.FileHandler('../logs/test.log')
file_handler1 =logging.FileHandler('../logs/test.log')
stream_handler logging.StreamHandler()

fmt = logging.Formatter('%(asctime)s - [%(levelname)s] - %(filename)s[%(lineno)d]:%(message)s')


file_handler.setFormatter(fmt)
file_handler1.setFormatter(fmt)
stream_handler.setFormatter(fmt)

2.4 .Formatter参数语句

‘%(asctime)s - [%(levelname)s] - %(filename)s[%(lineno)d]:%(message)s’

在这里插入图片描述

3. 封装logging模块 - 实战版 ⭐

在这里插入图片描述

3.1 配置config文件夹下project_config.py文件

测试和发布的时候通过更改配置文件可以更快的帮助我们提高效率

我们的需求是每个整点生成log日志文件,因此要结合time模块

import time

log_root_path = 'E:\\pythonProject\\pythonetl\\logs\\'
log_filename = f'pytel-{time.strftime("%Y%m%d-%H",time.localtime())}.log'
# print(log_filename)   pytel-20240902-16.logs

level = 10

time模块

import time

print(time.time())   # 距离1970年过了多少秒 (以秒为单位)
print(time.localtime()) #  time.struct_time(tm_year=2024, tm_mon=9, tm_mday=2, tm_hour=16, tm_min=10, tm_sec=57, tm_wday=0, tm_yday=246, tm_isdst=0)

print(time.strftime("%Y %m %d",time.localtime())) # 2024 09 02
print(time.strptime("2022-10-20 16:18:30","%Y-%m-%d %H:%M:%S"))

在这里插入图片描述

'''
常见的时间格式化的格式:
%Y:4位数字的年份:2024
%m:2位数字的月份:09
%d:2位数字的日期:02
%H:24小时制的小时
%M:2位数字的分钟
%S:2位数字的秒
如果要格式化为:2022-05-1510:05:55
'''

3.2 封装util文件夹下logging_until.py文件

这里不仅在终端进行了输出日志信息,同时在文件中保存了日志信息

import logging
import os

from config.project_config import log_root_path,log_filename,level
class Logging():
    def __init__(self,level=20):
        self.logger = logging.getLogger()
        self.logger.setLevel(level)


def init_logger():
    logger = Logging(level).logger

    # 缓存机制 避免日志重复输出  ⭐⭐
    if logger.handlers:
        return logger

    path = log_root_path+log_filename
    # 创建并打开文件
    with open(path, 'w') as file:
        # 文件被创建,但这里不写入任何内容,所以它是空的
        pass
    # 构造handler
    # 优化日志存储文件 StreamHandler
    stream_handler = logging.StreamHandler()
    file_handler = logging.FileHandler(
        filename=path,
        mode='a',
        encoding='utf-8'
    )

    fmt = logging.Formatter('%(asctime)s - [%(levelname)s] - %(filename)s[%(lineno)d]:%(message)s')

    stream_handler.setFormatter(fmt)
    file_handler.setFormatter(fmt)

    # 组合
    logger.addHandler(stream_handler)
    logger.addHandler(file_handler)

    return logger

3.3 其他模块下的mycode文件

  • 测试1
from util.logging_util import init_logger

logger = init_logger()
logger.info('This is a test!!')
logger.info('This is aaaaaaaaaaaaaaaaa test!!')

在这里插入图片描述
在这里插入图片描述

  • 测试2
from util.logging_util import init_logger

logger = init_logger()
logger.info('This is a test!!')
logger.info('This is aaaaaaaaaaaaaaaaa test!!')
logger.info('This is bbbbbbbbbbbbbbbbbbb test!!')

在这里插入图片描述
在这里插入图片描述

注意事项

若是在模块中这样运行代码

from util.logging_util import init_logger

#错误用法

#是因为python的缓存机制,第一次调用init_logger函数
#这时会添加filehandler streamhandle
init_logger().info("测试info1")
#第二次调用时,因为履存了rootlogger,所以再次会添加filehandler streamhandler
init_logger().info("测试info2")
#第三次就变成了三个hand1er
init_logger().info("测试info3")

在这里插入图片描述

解决

在logging_until.py的init_logger()中加入是否存在句柄的语句

def init_logger():
    logger = Logging(level).logger

    # 缓存机制 避免日志重复输出
    if logger.handlers:
        return logger
...

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

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

相关文章

Linux日志-btmp日志

作者介绍:简历上没有一个精通的运维工程师。希望大家多多关注作者,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux进阶部分又分了很多小的部分,我们刚讲完了Linux基础软件,下面是Linux日志。Linux 系统中的日志是记录系统活…

正向代理、反向代理

代理作为客户端和服务器的中间层,按照不同的维度可以分为不同的类型。 一种常见的划分方式是将代理分为正向代理(forward proxy)与反向代理(reverse proxy)。 根据实现代理的方式可以分为 HTTP 隧道代理、MITM 代理、…

ubuntu安装dnsmasq 做dns服务器

本文介绍在ubuntn22.04上安装dnsmasq用做自定义域名服务器,可以在公网上使用。 目标 准备两台不是同一个局域网内的服务器,其中A服务器是ubuntu22.04。在A上安装dnsmasq dns服务器,配置自定义域名,然后在B服务器上配置A做为dns服…

使用session实现单用户多端登录限制

基本流程: 首先获得当前浏览器访问服务器的session,然后根据用户的信息(如id等)在redis中查找,如果找到,并且和查找对应的session不同,则可以判断已经有其他设备登录过了,这个时候就…

Andorid 如何查看某个.so库的依赖

Android 手机中,如何查看其中某个.so 库依赖了其它哪些库?1.方法:使用android 手机中的readelf 命令.。2. 操作步骤:如查看libdolphin.so 的的依赖。 (1)adb shell 进入手机,进入libdolphin.so…

C++学习笔记----6、内存管理(一)---- 使用动态内存(2)

2.2、我的好朋友malloc怎么样了? 如果你是一个C程序员,对啦,我就是,你可能会想,malloc()函数怎么样了。在C语言中,malloc()用于分配一定数量的内存字节。总的来讲,使用malloc()简单直接。在C中m…

传统CV算法——图像特征算法之角点检测算法

文章目录 2. 角点检测2.1 角点概述2.1.1 概念2.1.2 角点的特点2.1.3 角点的检测2.1.4 角点的应用 2.2 角点检测算法2.2.1 Harris 角点2.2.1.1 Harris 角点介绍2.2.1.2 Harris计算流程1. 图像梯度2. 结构张量3. Harris响应函数4. 非极大值抑制5. 阈值化 2.2.1.3 Harris性质1. 旋…

《PCI Express体系结构导读》随记 —— 第II篇 第7章 PCIe总线的数据链路层与物理层(4)

接前一篇文章:《PCI Express体系结构导读》随记 —— 第II篇 第7章 PCIe总线的数据链路层与物理层(3) 7.1 数据链路层的组成结构 7.1.1 数据链路层的状态 数据链路层需要通过物理层监控PCIe链路的状态,并维护数据链路层的“控制与…

厂房电气火灾现场勘验要点

0前言 随着我国社会的发展,电气化水平提升,但随之而来的是频繁的电气火灾事故,对生活和生产造成重大危害。电气火灾是最常见的火灾类型,通常由电路短路、电压过高、电阻过大或电路超负荷引起,这些因素都可能导致火花并…

电脑怎么录屏?探索电脑录屏工具,三款高效工具推荐及使用指南

在数字化时代,电脑录屏已成为日常工作和学习中不可或缺的一部分。无论是制作教程、记录会议还是捕捉游戏精彩瞬间,一个好的录屏工具都能让这一切变得简单高效。今天,我们将为您介绍三款备受推崇的录屏软件:Windows自带的步骤记录器…

面向对象程序设计之链表 list 的简析(C++)

简介:链表是一个双向的结构,与string与vector不同的是他不支持[]访问,因为链表是由一个节点一个节点连接而成的,并不连续。我们可以在常数量级内对于链表进行插入与删除数据 1.构造函数 我们在cplusplus.com中可以查到链表总共有四…

无人机遥控器的材料组成!!!

1. 外壳 材料:遥控器外壳通常采用高强度塑料(如ABS、PC等)或轻质金属(如铝合金)制成。这些材料具有良好的抗冲击性、耐磨性和一定的耐腐蚀性,能够保护内部电子元件免受外界环境的影响。 特点:…

智能优化算法-秃鹰优化算法(BES)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1.内容介绍: 秃鹰搜索算法‌,它是一种基于自然界中秃鹰觅食行为启发的优化算法,旨在解决优化问题。该算法模仿了秃鹰在寻找猎物时的策略,结合了随机搜索和逐步优化的特点&#…

AGI系列(9)手把手带你玩转 Coze 画板节点

本文以智能体“日签卡片生成器”的制作来阐述 Coze 画板节点的使用方法。 效果演示 核心流程 日签卡片生成器工作流整体分为两部分: 工作流:其核心流程为通过用户输入的主题词生成卡片的标题、内容 图像流:通过LLM输出的内容在图像流完成卡…

【C++ Primer Plus习题】9.3

问题: 解答: #include <iostream> using namespace std;struct chaff {char dross[20];int slag; };int set_chaff(chaff& f, char* c, int n) {if (strlen(c) > 0){strcpy_s(f.dross, c);f.slag n;return 1;}return 0;}void show_cahff(const chaff& f) {c…

rabbitmq高可用集群搭建

需求分析基本情况 在进行RabbitMQ搭建时&#xff0c;我们基于现有的连接数据和业务需求进行了深入分析。目前的统计数据显示&#xff0c;连接数为631&#xff0c;队列数为80418。为了确保业务需求的顺利满足&#xff0c;我们需要在云产品和自建RabbitMQ消息队列服务之间做出选…

最新软件测试面试题,常见面试题及答案汇总,不怕拿不到offer

面试题包括以下十六个模块&#xff1a;软件测试基础&#xff0c;liunx基础&#xff0c;MySQL基础&#xff0c;web测试&#xff0c;APP测试&#xff0c;性能测试&#xff0c;selenium&#xff0c;Python基础&#xff0c;接口测试&#xff0c;lordrunner&#xff0c;计算机网络&a…

chapter11-枚举和注解——(注解)——day14

目录 433-override注解 434-Deprecated注解 435-SupressWarnings注解 436-JDK的元注解 433-override注解 434-Deprecated注解 435-SupressWarnings注解 436-JDK的元注解

华为云征文 | 华为云Flexus云服务器X实例之Docker环境下部署JmalCloud个人网盘

华为云征文 | 华为云Flexus云服务器X实例之Docker环境下部署JmalCloud个人网盘 前言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、JmalCloud介绍2.1 JmalCloud简介2.2 JmalCloud优点2.3 JmalCloud使…

Android Camera系列(一):SurfaceView+Camera

心行慈善&#xff0c;何需努力看经—《西游记》 本系列主要讲述Android开发中Camera的相关操作、预览方式、视频录制等&#xff0c;项目结构代码耦合性低&#xff0c;旨在帮助大家能从中有所收获&#xff08;方便copy :&#xff09; &#xff09;&#xff0c;对于个人来说也是一…