百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

Python日志模块logging python日志文件

ztj100 2024-12-26 17:44 14 浏览 0 评论

官方文档:

https://docs.python.org/2/library/logging.html

logging模块提供了两种记录日志的方式:

  • 第一种方式是使用logging提供的模块级别的函数
  • 第二种方式是使用Logging日志系统的四大组件

其实,logging所提供的模块级别的日志记录函数也是对logging日志系统相关类的封装而已。

logging模块定义的模块级别的常用函数:

logging.debug(msg, *args, **kwargs)创建一条严重级别为DEBUG的日志记录

logging.info(msg, *args, **kwargs)创建一条严重级别为INFO的日志记录

logging.warning(msg, *args, **kwargs)创建一条严重级别为WARNING的日志记录

logging.error(msg, *args, **kwargs)创建一条严重级别为ERROR的日志记录

logging.critical(msg, *args, **kwargs)创建一条严重级别为CRITICAL的日志记录

logging.log(level, *args, **kwargs)创建一条严重级别为level的日志记录

logging.basicConfig(**kwargs)对root logger进行一次性配置

函数说明

其中logging.basicConfig(**kwargs)函数用于指定“要记录的日志级别”、“日志格式”、“日志输出位置”、“日志文件的打开模式”等信息,其他几个都是用于记录各个级别日志的函数。

具体如下:

filename

将日志信息写入文件中,指定该设置项后日志信息就不会被输出到控制台了

filemode

指定日志文件的打开模式,默认为'a'。需要注意的是,该选项要在filename指定时才有效

format

指定日志格式字符串,即指定日志输出时所包含的字段信息以及它们的顺序。logging模块定义的格式字段下面会列出。

datefmt

指定日期/时间格式。需要注意的是,该选项要在format中包含时间字段%(asctime)s时才有效。

level

指定日志级别

stream

指定日志输出目标stream,如sys.stdout、sys.stderr以及网络stream。需要说明的是,stream和filename不能同时提供,否则会引发 ValueError异常

style

Python 3.2中新添加的配置项。指定format格式字符串的风格,可取值为'%'、'{'和'#39;,默认为'%'

handlers

Python 3.3中新添加的配置项。该选项如果被指定,它应该是一个创建了多个Handler的可迭代对象,这些handler将会被添加到root logger。需要说明的是:filename、stream和handlers这三个配置项只能有一个存在,不能同时出现2个或3个,否则会引发ValueError异常。

上面的时间需要使用format中包含时间段,过于format还有如下参数:

asctime

%(asctime)s

日志事件发生的时间--人类可读时间,如:2003-07-08 16:49:45,896

created

%(created)f

日志事件发生的时间--时间戳,就是当时调用time.time()函数返回的值

relativeCreated

%(relativeCreated)d

日志事件发生的时间相对于logging模块加载时间的相对毫秒数(目前还不知道干嘛用的)

msecs

%(msecs)d

日志是发生事件的毫秒部分

levelname

%(levelname)s

该日志记录的文字形式的日志级别('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')

levelno

%(levelno)s

日志记录的数字形式的日志级别(10, 20, 30, 40, 50)

name

%(name)s

所使用的日志器名称,默认是'root',因为默认使用的是 rootLogger

message

%(message)s

日志记录的文本内容,通过 msg % args计算得到的

pathname

%(pathname)s

调用日志记录函数的源码文件的全路径

filename

%(filename)s

pathname的文件名部分,包含文件后缀

module

%(module)s

filename的名称部分,不包含后缀

lineno

%(lineno)d

调用日志记录函数的源代码所在的行号

funcName

%(funcName)s

调用日志记录函数的函数名

process

%(process)d

进程ID

processName

%(processName)s

进程名称,Python 3.1新增

thread

%(thread)d

线程ID

threadName

%(thread)s

线程名称

一、使用logging提供的模块级别的函数记录日志

  • 可以通过logging模块定义的模块级别的方法去完成简单的日志记录
  • 只有级别大于或等于日志记录器指定级别的日志记录才会被输出,小于该级别的日志记录将会被丢弃。

logging的日志级别由低到高分为 debug(), info(), warning(), error() and critical() 5个级别

CRITICAL(50) > ERROR(40) > WARNING(30) > INFO(20) > DEBUG(10)

简单使用示例:

import logging

logging.basicConfig(filename="E:\\logging\\abc.log", format='%(asctime)s %(message)s', datefmt='%Y-%m-%d %I:%M:%S %p', level=logging.WARNING)

logger = logging.getLogger()

logger.debug("The debug.")
logger.info("The info.")
logger.warning("The warning.")
logger.error("The error.")
logger.critical("The critical.")

print(logger.level)

运行结果:

查看E:\\logging\\abc.log文件中的内容,如下:

可以看到,由于设置的日志级别为WARNING,所以只打印了比WARNING级别更高的日志。

二、使用logging四大组件记录日志

logging模块的四大组件:

logger:提供日志接口,供应用代码使用。logger最长用的操作有两类:配置和发送日志消息。可以通过logging.getLogger(name)获取logger对象,
        如果不指定name则返回root对象,多次使用相同的name调用getLogger方法返回同一个logger对象

handler:将日志记录(log record)发送到合适的目的地(destination),比如文件,socket等。一个logger对象可以通过addHandler方法添加多个handler,
         每个handler又可以定义不同日志级别,以实现日志分级过滤显示

filter:提供方式决定一个日志记录是否发送到handler

formatter:指定日志记录输出的具体格式。formatter的构造方法需要两个参数:消息的格式字符串和日期字符串,这两个参数都是可选的

如上面所说,logging.basicConfig()函数中可通过具体参数来更改logging模块的行为

日志同时打印到屏幕和文件:

import logging

# 创建一个日志对象
logg = logging.getLogger("测试日志")
# 定义一个模板
FORMATTER = logging.Formatter("%(asctime)s - %(name)s - [%(lineno)d] - %(message)s")

# 创建一个屏幕流
p_stream = logging.StreamHandler()
# 创建一个文件流
f_stream = logging.FileHandler("log.log", mode="a", encoding="utf-8")

# 将流绑定到模板
p_stream.setFormatter(FORMATTER)
f_stream.setFormatter(FORMATTER)

# 将日志和流进行绑定
logg.addHandler(p_stream)
logg.addHandler(f_stream)

# 设置日志记录等级
logg.setLevel(logging.DEBUG)

# 打印日志信息
logg.debug("this is Debug")
logg.info("this is info")
logg.warning("this is warning")
logg.error("this is error")
logg.critical("this is critical")

运行结果:

如果想为多个用户创建不同的日志,只需要创建流时创建不同的日志即可,而不需要创建多个日志对象,如果情况特殊考虑单独在创建一个对象。其实我们可以在创建流的时候直接指定日志等级。流氓的等级是优先于日志对象的。

如下创建两个流:

import logging

# 创建一个日志对象
logg = logging.getLogger("测试日志")

# 创建一个程序员模板和老板模板
CORE_FORMATTER = logging.Formatter("%(asctime)s - %(name)s - [%(lineno)d] - %(message)s")
BOOS_FORMATTER = logging.Formatter("%(asctime)s - %(message)s")

# 创建一个程序员的流和一个老板的流
core_stream = logging.FileHandler("core.log", mode="a", encoding="utf-8")
boos_stream = logging.FileHandler("boos.log", mode="a", encoding="utf-8")

# 设置日志等级(老板的日志等级设置WARNING)
boos_stream.setLevel(logging.WARNING)

# 将流绑定到模板
core_stream.setFormatter(CORE_FORMATTER)
boos_stream.setFormatter(BOOS_FORMATTER)

# 将日志和流进行绑定
logg.addHandler(core_stream)
logg.addHandler(boos_stream)

# 设置日志记录等级
logg.setLevel(logging.DEBUG)

# 打印日志信息
logg.debug("this is Debug")
logg.info("this is info")
logg.warning("this is warning")
logg.error("this is error")
logg.critical("this is critical")

运行结果:

这样我们便创建了两种不同的日志

、日志分割

将日志信息输出到一个单一的文件中,随着应用程序的持续使用,该日志文件会越来越庞大,进而影响系统的性能。因此,有必要对日志文件按某种条件进行切分。

分割日志的触发条件:大小、日期,或者大小加上日期。

说是切分,实际上是,当一个日志文件达到触发条件后,对日志文件进行重命名,之后再新建原来名称的日志文件(此时就是空文件了),新产生的日志就写入新的日志文件。

为啥叫回滚呢?当分割的日志文件达到指定数目的上限个数时,最老的日志文件就会被删除。

logging库提供了2个可以用于日志滚动的class,一个是RotatingFileHandler,它主要是根据日志文件的大小进行滚动;另一个是TimeRotatingFileHandler,它主要是根据时间进行滚动。在实际应用中,通常根据时间进行滚动。

TimedRotatingFileHandler的构造函数定义如下:

TimedRotatingFileHandler(filename [,when [,interval [,backupCount]]])

filename 是输出日志文件名的前缀,比如log/myapp.log

when 的定义如下:

“S”: Seconds

“M”: Minutes

“H”: Hours

“D”: Days

“W”: Week day (0=Monday)

“midnight”: Roll over at midnight

interval:指等待多少个单位when的时间后,Logger会自动重建文件,当然,这个文件的创建取决于filename+suffix,若这个文件跟之前的文件有重名,则会自动覆盖掉以前的文件,所以有些情况suffix要定义的不能因为when而重复。

backupCount:保留日志个数。默认的0是不会自动删除掉日志。若设3,则在文件的创建过程中库会判断是否有超过这个3,若超过,则会从最先创建的开始删除。

按秒切分示例:

import time
import logging
import logging.handlers
import os

# 如果日志文件夹不存在,则创建
log_dir = "log-second"  # 日志存放文件夹名称
log_path = os.getcwd() + os.sep + log_dir
if not os.path.isdir(log_path):
    os.makedirs(log_path)

# logging初始化工作
logging.basicConfig()

# 初始化loggger
test = logging.getLogger('test')
test.setLevel(logging.INFO)

# 添加TimedRotatingFileHandler
# 定义一个1秒换一次log文件的handler
# 保留3个旧log文件
timefilehandler = logging.handlers.TimedRotatingFileHandler(
    log_dir + os.sep + "log",
    when='S',
    interval=1,
    backupCount=3
)

# 设置后缀名称,跟strftime的格式一样
timefilehandler.suffix = "%Y-%m-%d_%H-%M-%S.log"

formatter = logging.Formatter('%(asctime)s|%(name)-12s: %(levelname)-8s %(message)s')
timefilehandler.setFormatter(formatter)
test.addHandler(timefilehandler)

n = 6
while n > 0:
    test.info("这是一个时间分割的测试程序")
    time.sleep(1)
    n -= 1

运行结果:

注意:

timefilehandler.suffix的设置一定要和时间单位相符,不如按秒切分,就必须设置timefilehandler.suffix= "%Y-%m-%d_%H-%M-%S.log",否则就不能删除旧文件了。按天、按分钟切分也是如此。

RotatingFileHandler基于文件大小切分

示例:

import time
# import logging
import os
import logging.handlers

# 如果日志文件夹不存在,则创建
log_dir = "log-size"  # 日志存放文件夹名称
log_path = os.getcwd() + os.sep + log_dir
if not os.path.isdir(log_path):
    os.makedirs(log_path)

# logging初始化工作
logging.basicConfig()

# 初始化loggger
test_02 = logging.getLogger('test_02')
test_02.setLevel(logging.INFO)

# 写入文件,如果单个文件超过100个Bytes,则写入下一个文件,最多保留5个文件
handler = logging.handlers.RotatingFileHandler(
    'log-size/test_02.log', maxBytes=100, backupCount=5)

formatter = logging.Formatter('%(asctime)s|%(name)-12s: %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
# 设置后缀名称,跟strftime的格式一样
test_02.addHandler(handler)

n = 6
while n > 0:
    test_02.info("这是一个大小分割的测试程序")
    time.sleep(1)
    n -= 1

运行结果:

-----------------------------------------------------------------------------

推荐:

详细全面:https://www.cnblogs.com/yyds/p/6901864.html

https://www.cnblogs.com/hanmk/p/10448963.html

相关推荐

Sublime Text 4 稳定版 Build 4113 发布

IT之家7月18日消息知名编辑器SublimeText4近日发布了Build4113版本,是SublimeText4的第二个稳定版。IT之家了解到,SublimeTe...

【小白课程】openKylin便签贴的设计与实现

openKylin便签贴作为侧边栏的一个小插件,提供便捷的文本记录和灵活的页面展示。openKylin便签贴分为两个部分:便签列表...

“告别 Neovim!为什么我投奔了刚开源的 Zed 编辑器?”

...

壹啦罐罐 Android 手机里的 Xposed 都装了啥

这是少数派推出的系列专题,叫做「我的手机里都装了啥」。这个系列将邀请到不同的玩家,从他们各自的角度介绍手机中最爱的或是日常使用最频繁的App。文章将以「每周一篇」的频率更新,内容范围会包括iOS、...

电气自动化专业词汇中英文对照表(电气自动化专业英语单词)

专业词汇中英文对照表...

Python界面设计Tkinter模块的核心组件

我们使用一个模块,我们要熟悉这个模块的主要元件。如我们设计一个窗口,我们可以用Tk()来完成创建;一些交互元素,按钮、标签、编辑框用到控件;怎么去布局你的界面,我们可以用到pack()、grid()...

以色列发现“死海古卷”新残片(死海古卷是真的吗)

编译|陈家琦据艺术新闻网(artnews.com)报道,3月16日,以色列考古学家发现了死海古卷(DeadSeaScrolls)新残片。新出土的羊皮纸残片中包括以希腊文书写的《十二先知书》段落,这...

鸿蒙Next仓颉语言开发实战教程:订单列表

大家上午好,最近不断有友友反馈仓颉语言和ArkTs很像,所以要注意不要混淆。今天要分享的是仓颉语言开发商城应用的订单列表页。首先来分析一下这个页面,它分为三大部分,分别是导航栏、订单类型和订单列表部分...

哪些模块可以用在 Xposed for Lollipop 上?Xposed 模块兼容性解答

虽然已经有了XposedforLollipop的安装教程,但由于其还处在alpha阶段,一些Xposed模块能不能依赖其正常工作还未可知。为了解决大家对于模块兼容性的疑惑,笔者尽可能多...

利用 Fluid 自制 Mac 版 Overcast 应用

我喜爱收听播客,健身、上/下班途中,工作中,甚至是忙着做家务时。大多数情况下我会用MarcoArment开发的Overcast(Freemium)在iPhone上收听,这是我目前最喜爱的Po...

Avalonia日志组件实现与优化指南(ar日志表扣)

...

浅色Al云食堂APP代码(三)(手机云食堂)

以下是进一步优化完善后的浅色AI云食堂APP完整代码,新增了数据可视化、用户反馈、智能推荐等功能,并优化了代码结构和性能。项目结构...

实战PyQt5: 121-使用QImage实现一个看图应用

QImage简介QImage类提供了独立于硬件的图像表示形式,该图像表示形式可以直接访问像素数据,并且可以用作绘制设备。QImage是QPaintDevice子类,因此可以使用QPainter直接在图...

滚动条隐藏及美化(滚动条隐藏但是可以滚动)

1、滚动条隐藏背景/场景:在移动端,滑动的时候,会显示默认滚动条,如图1://隐藏代码:/*隐藏滚轮*/.ul-scrool-box::-webkit-scrollbar,.ul-scrool...

浅色AI云食堂APP完整代码(二)(ai 食堂)

以下是整合后的浅色AI云食堂APP完整代码,包含后端核心功能、前端界面以及优化增强功能。项目采用Django框架开发,支持库存管理、订单处理、财务管理等核心功能,并包含库存预警、数据导出、权限管理等增...

取消回复欢迎 发表评论: