Python -- logging日志处理模块

python Logging日志记录模块详解 写在篇前   logging是Python的一个标准库,其中定义的函数和类为应用程序和库的开发实现了一个灵活的事件日志系统。Python logging 的配置由四个部分组成:Logger、Handlers、Filter、Formatter。本篇博客将依次介绍这四个主要部分以及logging的基本应用。   在开始之前,我们有必要先了解一下,什么时候我们才有必要使用logging模块,什么时候抛出... 阅读详情

日志级别

日志级别Level数值
CRITICAL50
ERROR40
WARNING30,默认级别
INFO20
DEBUG10
NOTSET0

日志级别指的是产生日志的事件的严重程度

  • 设置一个级别后,严重程度低于设置值的日志消息将被忽略
  • 级别定义一般都写在配置文件里
  • WARNING为默认级别,低于其的为低级别,反之为高级别
  • 其方法有:
    debug()、 info()、 warning()、 error() 和 critical()
import logging

logging.basicConfig(level=logging.INFO)

logging.info('test')

# 执行结果
INFO:root:test

格式字符串

属性名格式描述
日志消息内容%(message)sThe logged message, computed as msg % args. 当调用Formatter.format()时设置
asctime%(asctime)s创建LogRecord时的可读时间。默认情况下,它的格式为'2003-07-08 16:49:45,896'(逗号后面的数字是毫秒部分的时间)
函数名%(funcName)s日志调用所在的函数名
日志级别名称%(levelname)s消息的级别名称'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
日记级别数值%(levelno)s消息的级别数字 ,对应DEBUG, INFO, WARNING, ERROR, CRITICAL
行号%(lineno)d日志调用所在的源码行号
模块%(module)s模块(filename的名字部分)
进程ID%(process)d进程 ID
线程ID%(thread)d线程 ID
进程名称%(processName)s进程名
线程名称%(threadName)s线程名字
logger名称%(name)slogger名字

注意:funcName、threadName、processName都是小驼峰

举例

默认级别

import logging

FORMAT = '%(asctime)-15s\tThread info:%(thread)d %(threadName)s %(message)s'
logging.basicConfig(format=FORMAT)

logging.info('I am {}'.format(20))
logging.warning('I am {}'.format(20))

# 执行结果
2019-06-11 17:37:41,219	Thread info:348680 MainThread I am 20

由于默认级别是WARNING,所以INFO的结果不显示

构建消息

import logging

FORMAT = '%(asctime)-15s\tThread info:%(thread)d %(threadName)s %(message)s'
logging.basicConfig(format=FORMAT, level=logging.INFO)

logging.info('I am {}'.format(20)) # 单一字符串
logging.warning('I am %d %s', 20, 'years old.') # c风格

# 执行结果
2019-06-11 17:55:48,932	Thread info:350316 MainThread I am 20
2019-06-11 17:55:48,932	Thread info:350316 MainThread I am 20 years old.

上例是基本的使用方法,大多数时候,使用的是info,正常运行信息的输出

日志级别和格式字符串扩展的例子

  • 可插入指定打印字符,使用字典
import logging

FORMAT = '%(asctime)-15s\tThread info:%(thread)d %(threadName)s %(message)s %(hello)s'
logging.basicConfig(format=FORMAT, level=logging.WARNING) # 级别WARNING

d = {'hello': 'world'}
logging.info('I am {}'.format(20), extra = d) # 级别INFO
logging.warning('I am %d %s', 20, 'years old.',extra = d) # 级别WARNING

# 执行结果
2019-06-11 17:59:14,671	Thread info:350340 MainThread I am 20 years old. world

修改日期格式

import logging

logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%Y/%m/%d %I:%M:%S')
logging.warning('this event was logged.')

# 执行结果
2019/06/11 06:02:42 this event was logged.

输出到文件

import logging

logging.basicConfig(format='%(asctime)s %(message)s', filename='d:/test.log')
logging.warning('this event was logged.')

在这里插入图片描述
注意:此时控制台没有输出内容
在这里插入图片描述

  • filename设置日志文件
  • filemode设置读写模式
    默认a,追加模式,将结果写入文件,文件没有 创建文件

Logger类

在logging模块中,顶层代码中有

root = RootLogger(WARNING) # 大约在1731行处。指定根Logger对象的默认级别。就在basicConfig函数上面
Logger.root = root # 为类Logger增加类属性root
  • logging模块加载的时候,会创建一个全局对象root,它是一个RootLogger实例,即root logger。根Logger对象的默认级别是WARNING
  • RootLogger类继承自Logger类
  • 类Logger初始化方法签名是(name, level=0)
  • 类RootLogger初始化方法签名(level),本质上调用的是 Logger.__init__(self, "root", WARNING)
  • 调用logging.basicConfig来调整级别,就是对这个 根Logger 的级别进行修改

构造

Logger实例的构建,使用Logger类也行,但推荐getLogger函数

Logger.manager = Manager(Logger.root) # 1733行,为Logger类注入一个manager类属性
	
def getLogger(name=None):
	"""
	Return a logger with the specified name, creating it if necessary.
	If no name is specified, return the root logger.
	"""
	if name:
		return Logger.manager.getLogger(name)
	else:
		return root # 没有指定名称,返回根logger

使用工厂方法返回一个Logger实例

  • 指定name,返回一个名称为name的Logger实例。如果再次使用相同的名字,返回同一个实例。背后使用一个字典保证同一个名称返回同一个Logger实例
  • 未指定name,返回根Logger实例
import logging

a = logging.Logger('hello', 20)
b = logging.Logger('hello', 30)
print(a, id(a))
print(b, id(b))

c = logging.getLogger('hello')
d = logging.getLogger('hello')
print(c, id(c))
print(d, id(d))

# 执行结果
<Logger hello (INFO)> 35484168
<Logger hello (WARNING)> 35484560
<Logger hello (WARNING)> 42988600
<Logger hello (WARNING)> 42988600

层次结构

Logger是层次结构的,使用 . 点号分割,如’a’、‘a.b’或’a.b.c.d’,a是a.b的父parent,a.b是a的子child。对于foo来说,名字为foo.bar、foo.bar.baz、foo.bam都是 foo的后代

import logging

# 父子层次关系
# 根logger
root = logging.root
print(root, id(root))
print('-' * 30)

root = logging.getLogger()
print(root, id(root))
print(root.name, type(root), root.parent) # 根logger没有父
print('=' * 30)

parent = logging.getLogger(__name__)# 模块级logger
print(parent.name, type(parent), id(parent.parent), id(parent))
print('~' * 30)

child = logging.getLogger("{}{}".format(__name__, '.child')) # 子logger
print(child.name, type(child), id(child.parent), id(child))

# 执行结果
<RootLogger root (WARNING)> 43875464
------------------------------
<RootLogger root (WARNING)> 43875464
root <class 'logging.RootLogger'> None
==============================
__main__ <class 'logging.Logger'> 43875464 41683376
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__main__.child <class 'logging.Logger'> 41683376 41683040

Level级别设置

每一个logger实例都有级别

import logging

FORMAT = '%(asctime)-15s\tThread info: %(thread)d %(threadName)s [%(message)s]'
logging.basicConfig(format=FORMAT, level=logging.INFO)

logging = logging.getLogger(__name__)
print(logging.name, type(logging), logging.level) # 新的logger实例的level是什么
logging.info('1 info')
print(logging.getEffectiveLevel()) # 等效级别,从哪里来的

logging.setLevel(28) # 设置logger是level
print(logging.getEffectiveLevel(), logging.level)
logging.info('2 info')

logging.setLevel(42)
logging.warning('3 warning')
logging.error('4 error')
logging.critical('5 critical')

# 执行结果
__main__ <class 'logging.Logger'> 0
2019-06-12 09:09:14,049	Thread info: 4192 MainThread [1 info]
20
2019-06-12 09:09:14,049	Thread info: 4192 MainThread [5 critical]
28 28

每一个logger实例,都有一个等效的level
logger对象可以在创建后动态的修改自己的level
等效level决定着logger实例能输出什么级别信息

Handler

Handler 控制日志信息的输出目的地,可以是控制台、文件

  • 可以单独设置level
  • 可以单独设置格式
  • 可以设置过滤器

Handler类层次

  • Handler
    • StreamHandler # 不指定使用sys.stderr
      • FileHandler # 文件
      • _StderrHandler # 标准输出
    • NullHandler # 什么都不做

日志输出其实是Handler做的,也就是真正干活的是Handler
在logging.basicConfig函数中,如下:

if handlers is None:
	filename = kwargs.pop("filename", None)
	mode = kwargs.pop("filemode", 'a')
	if filename:
		h = FileHandler(filename, mode)
	else:
		stream = kwargs.pop("stream", None)
		h = StreamHandler(stream)
	handlers = [h]
  • 如果设置文件名,则为根Logger加一个输出到文件的FileHandler;如果没有设置文件名,则为根Logger加一个StreamHandler,默认输出到sys.stderr
  • 也就是说,根logger一定会至少有一个handler的

Handler的初始的level

import logging

FORMAT = '%(asctime)s %(name)s %(message)s'
logging.basicConfig(format=FORMAT, level=logging.INFO)

logger = logging.getLogger('test')
print(logger.name, type(logger))

logging.info('line 1')

handler = logging.FileHandler('d://l1.log', 'w') # 创建handler
logger.addHandler(handler) # 给logger对象绑定一个handler

logger.info('line 2')
  • 控制台输出内容
test <class 'logging.Logger'>
2019-06-12 09:25:05,022 root line 1
2019-06-12 09:25:05,022 test line 2
  • l1.log文件内内容
line 2

Handler 的初始的level是 0

日志流

level的继承

import logging

logging.basicConfig(format="%(asctime)s %(name)s [%(message)s]")

log1 = logging.getLogger('s')
print(log1.level, log1.getEffectiveLevel())
log1.info('1 info')

log2 = logging.getLogger('s.s1')
print(log2.level, log2.getEffectiveLevel())
log2.info('2 info')
print('-' * 30)

log1.setLevel(20)
log1.info('3 info')
print(log1.level, log1.getEffectiveLevel())
print(log2.level, log2.getEffectiveLevel())
log2.info('4 info')

log2.setLevel(30)
print(log2.level, log2.getEffectiveLevel())
log2.info('5 info')

# 执行结果
2019-06-12 09:30:49,760 s [3 info]
2019-06-12 09:30:49,760 s.s1 [4 info]
0 30
0 30
------------------------------
20 20
0 20
30 30

logger实例

  • 如果不设置level,则初始level为0
  • 如果设置了level,就优先使用自己的level,否则,继承最近的祖先的level
  • 信息是否能够从该logger实例上输出,就是要看当前函数的level是否大于等于logger的有效level,否则输出不了

继承关系及信息传递

  • 每一个Logger实例的level如同入口,让水流进来,如果这个门槛太高,信息就进不来。例如log3.warning('log3'),如果log3定义的级别高,就不会有信息通过log3
  • 如果level没有设置,就用父logger的,如果父logger的level没有设置,继续找父的父的,最终可以找到root上,如果root设置了就用它的,如果root没有设置,root的默认值是WARNING
  • 消息传递流程
  1. 如果消息在某一个logger对象上产生,这个logger就是当前logger,首先消息level要和当前logger的EffectiveLevel比较,如果低于当前logger的EffectiveLevel,则流程结束;否则生成log记录
  2. 日志记录会交给当前logger的所有handler处理,记录还要和每一个handler的级别分别比较,低的不处理,否则按照handler输出日志记录
  3. 当前logger的所有handler处理完后,就要看自己的propagate属性,如果是True表示向父logger传递这个日志记录,否则到此流程结束
  4. 如果日志记录传递到了父logger,不需要和父logger的level比较,而是直接交给父的所有handler,父logger成为当前logger。重复2、3步骤,直到当前logger的父logger是None退出,也就是说当前logger最后一般是root logger(是否能到root logger要看中间的logger是否允许propagate)
  • logger实例初始的propagate属性为True,即允许向父logger传递消息
  • logging.basicConfig函数
    • 如果root没有handler,就默认创建一个StreamHandler,如果设置了filename,就创建一个FileHandler
    • 如果设置了format参数,就会用它生成一个Formatter对象,否则会生成缺省Formatter,并把这个formatter加入到刚才创建的handler上,然后把这些handler加入到root.handlers列表上。level是设置给root logger的
    • 如果root.handlers列表不为空,logging.basicConfig的调用什么都不做

官方日志流转图

在这里插入图片描述

  • 参考logging.Logger类的callHandlers方法

实例

import logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)-10s [%(message)s]")

# 根logger操作
root = logging.getLogger()
root.setLevel(logging.ERROR)
print('root', root.handlers)

# 增加handler
import sys
h0 = logging.StreamHandler(sys.stdout)
h0.setLevel(logging.WARNING)
root.addHandler(h0)
print('root', root.handlers)

for h in root.handlers:
    print('root handler = {}, formattrt = {}'.format(
        h, h.formatter._fmt if h.formatter else ''))

logging.error('root test~~~~~')

# logger s
log1 = logging.getLogger('s')
log1.setLevel(logging.ERROR)
h1 = logging.FileHandler('d:/test.log')
h1.setLevel(logging.WARNING)
log1.addHandler(h1)
print(log1.name, log1.handlers)
log1.warning('s test ------') # 打印不了,但是文件中有
print('-' * 30)

# logger s.s1
log2 = logging.getLogger()
log2.setLevel(logging.CRITICAL)
h2 = logging.FileHandler('d:/test.log')
h2.setLevel(logging.WARNING)
log2.addHandler(h2)
print(log2.name, log2.handlers)
log2.error('s.s1 test ====')
print('-' * 30)

# logger s.s1.s2
log3 = logging.getLogger('s.s1.s2')
log3.setLevel(logging.INFO)# 级别最低
print(log3.getEffectiveLevel())
log3.info('s.s1.s2 test ingo ====')
print(log3.name, log3.handlers)

执行结果

2019-06-12 22:04:14,174 root       [root test~~~~~]
root [<StreamHandler <stderr> (NOTSET)>]
2019-06-12 22:04:14,175 s.s1.s2    [s.s1.s2 test ingo ====]
root [<StreamHandler <stderr> (NOTSET)>, <StreamHandler <stdout> (WARNING)>]
root handler = <StreamHandler <stderr> (NOTSET)>, formattrt = %(asctime)s %(name)-10s [%(message)s]
root handler = <StreamHandler <stdout> (WARNING)>, formattrt = 
root test~~~~~
s [<FileHandler d:\test.log (WARNING)>]
------------------------------
root [<StreamHandler <stderr> (NOTSET)>, <StreamHandler <stdout> (WARNING)>, <FileHandler d:\test.log (WARNING)>]
------------------------------
20
s.s1.s2 []

Formatter

logging的Formatter类,它允许指定某个格式的字符串。如果提供None,那么'%(message)s'将会作为默认值

import logging
import sys

FORMATSTR = "%(asctime)s\t%(name)s\t%(thread)s,%(message)s"

logging.basicConfig(format=FORMATSTR, datefmt="%Y/%m/%d %H:%M:%S", level=logging.INFO)

log1 = logging.getLogger('log1')
log1.propagate = True

h = logging.FileHandler('d:/{}.log'.format(__name__))
log1.addHandler(h)
print(log1.handlers[0].formatter)

f = logging.Formatter('*** %(message)s ***')
h.setFormatter(f)
print(log1.handlers[0].formatter._fmt)

h.setLevel(logging.WARNING)

log1.info('log1 test info string') # %(message)s

执行结果
在这里插入图片描述

  • 修改颜色为黑色
    在logging.basicConfig()增加一句stream=sys.stdout
logging.basicConfig(format=FORMATSTR, datefmt="%Y/%m/%d %H:%M:%S", level=logging.INFO,stream=sys.stdout)

结果如下
在这里插入图片描述

import logging
import sys

FORMATSTR = "root\t[%(name)s]\t%(thread)s,%(message)s"

logging.basicConfig(format=FORMATSTR,level=logging.INFO,stream=sys.stdout)

log1 = logging.getLogger('log1')
log1.propagate = True

h = logging.StreamHandler(sys.stdout)
log1.addHandler(h)

f = logging.Formatter('log1\t[%(name)s]\t%(message)s')
h.setFormatter(f)

log2 = logging.getLogger('log1.log2')

log2.info('log2 test info string') # %(message)s

# 执行结果
log1	[log1.log2]	log2 test info string
root	[log1.log2]	5160,log2 test info string

Filter

Filter分为2种:

  • 可以为handler增加过滤器,所以这种过滤器只影响某一个handler,不会影响整个处理流程
  • 如果过滤器增加到logger上,就会影响流程

filter如果为空 恒等True

import logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)-19s [s(message)s]")

# logger s
log1 = logging.getLogger('s')
log1.setLevel(logging.WARNING)
h1 = logging.StreamHandler()
h1.setLevel(logging.INFO)
f1 = logging.Formatter('log1-h1 %(message)s')
h1.setFormatter(f1)
log1.addHandler(h1)

# logger s.s1
log2 = logging.getLogger('s.s1')
print(log2.getEffectiveLevel()) # 继承父logger,就是s的level
h2 = logging.StreamHandler()
h2.setLevel(logging.INFO)
f2 = logging.Formatter('log2-h2 %(message)s')
h2.setFormatter(f2)

# 增加Filter
filter = logging.Filter('s') # 过滤器
h2.addFilter(filter) # h2上增加了该过滤器
print(filter.name, filter.nlen) # 名字s,名字长度1
log2.addHandler(h2)

log2.warning('log test warning string')

# loger s.s2
log3 = logging.getLogger('s.s1.s2')
print(log3.name, log3.getEffectiveLevel())
log3.warning('log3 test warning string')
  • 执行结果
30
s 1
s.s1.s2 30
log2-h2 log test warning string
log1-h1 log test warning string
2019-06-13 11:14:17,285 s.s1                [s(message)s]
log2-h2 log3 test warning string
log1-h1 log3 test warning string
2019-06-13 11:14:17,285 s.s1.s2             [s(message)s]

消息log2的,它的名字是s.s1,因此过滤器名字设置为s或s.s1,消息就可以通过,但是如果是其他就不能通过,不设置过滤器名字,所有消息通过

过滤器核心源代码

在logging.Filter类的filter方法中

class Filter(object):
    def __init__(self, name=''):
        self.name = name
        self.nlen = len(name)

    def filter(self, record):
        if self.nlen == 0:
            return True
        elif self.name == record.name:
            return True
        elif record.name.find(self.name, 0, self.nlen) != 0:
            return False
        return (record.name[self.nlen] == ".")
  • record.name.find(self.name, 0, self.nlen) != 0本质上就是等价于record.name.startswith(filter.name)
  • 如果上面测试通过,还要求return (record.name[self.nlen] == ".",也就是说不但要以filter.name开头,而且下一个字符必须是.点号,否则返回False

上例代码中增加下面代码,能输出吗

log4 = logging.getLogger('s4')
log4.warning('s4 ~~~~')
  • 能输出,因为因为s4根本和上面的没有父子关系,它的父就是root,会直接传播给root logger
别再手动改文献了!手把手教你定制Mendeley的GB/T 7714-2005引用格式(附常见问题修复) 本文详细指导如何定制Mendeley的GB/T 7714-2005引用格式,解决科研文献管理中的常见问题。通过深度解析Mendeley样式编辑器,精准控制作者显示规则、出版社信息精简及期刊页码处理,实现参考文献一键合规。附常见问题修复和实战调试方法,大幅提升学术写作效率。 阅读详情

相关推荐

别再手动算重量了!用C++给UG/NX写个自动计算零件质量与质心的插件(附完整源码)

本文详细介绍了如何使用C++为UG/NX开发智能质量分析插件,实现零件质量与质心的自动计算。通过结合NXOpen和UF_MODL API,设计高效的数据结构和批量处理机制,大幅提升机械设计效率。文章包含完整源码和实用技巧,帮助工程师告别手动计算,适用于复杂装配体的自动化工程计算。

weixin_30247307的博客 130

Python的Logging模块

万字长文带你学透Python的Logging模块,文章通俗易懂且带有相关代码演示,具体案例助你理解

m0_60981735的博客 1万+

告别U盘!在Ubuntu 22.04上从零搭建PXE网络装机服务器(支持UEFI/Legacy双启动)

本文详细介绍了在Ubuntu 22.04上搭建PXE网络装机服务器的完整流程,支持UEFI/Legacy双启动模式。通过配置DHCP、TFTP和HTTP服务,实现无需U盘的高效批量系统部署,解决传统安装方式的介质依赖、版本控制和时间成本问题,显著提升机房维护和设备部署效率。

weixin_42569329的博客 248

Python 日志详解(logging)

Python 日志详解(logging)

鱼丸丶粗面 8908

从零开始编写一个上位机(串口助手)QT Creator + C++

提示:本博客作为学习笔记,有错误的地方希望指正,此文可能会比较长,作为学习笔记的积累,希望对来着有帮助。   绪论:笔者这里使用的是QTCreator和C++来实现一个简单的串口上位机的开发的简单过程,使用到C++,主要是为了后面使用Python开发上位机打下基础。这里主要分为初识C++的一些基本知识,其次是QT Creator的使用。特别声明感谢【北京迅为】嵌入式学习之QT学习篇的学习视频,这里的学习笔记就是根据视频中的内容实战记录下来的。 文章目录一、C++知识1、初识C++2、C++输入输出控制2.1

believe666的博客 4万+

uni-app项目中引入Vant UI组件库(完美避坑!!!)纯净版

uni-app项目中引入Vant UI组件库(纯净版--无uni-ui)

Wzmlzrr的博客 3万+

python 中的 logging 详解

什么是 logging.StreamHandler()?它为什么将信息输出到控制台?logging.getLogger().addHandler(console) 到底做了什么?想解答这些问题,探索 logging 更丰富的用法,于是我去查看了官方文档教程,在这里对这次学习进行记录整理。本文不追究文档的细节,对基础的知识也默认已知,主要目的是建立对 logging 整体架构和工作方式的认识。

撒旦先生的博客 4967

QT 面试题汇总

一、讲述Qt信号槽机制与优势与不足 优点:①类型安全。需要关联的信号槽的签名必须是等同的。即信号的参数类型和参数个数同接受该信号的槽的参数类型和参数个数相同。若信号和槽签名不一致,编译器会报错。 ②松散耦合。信号和槽机制减弱了Qt对象的耦合度。激发信号的Qt对象无需知道是那个对象的那个信号槽接收它发出的信号,它只需在适当的时间发送适当的信号即可,而不需要关心是否被接受和那个对象接受了。Qt就保证了适当的槽得到了调用,即使关联的对象在运行时被删除。程序也不会奔溃。 ...

编程菜鸟 4万+

Python日志库logging总结-可能是目前为止将logging库总结的最好的一篇文章

Python的longing模块就是为了记录日志使用的,而且是线程安全的,以为着使用它完全不用担心因日志模块的异常导致程序崩溃。 1. logging模块的简单使用 import logging logging.basicConfig( level=logging.DEBUG, format="%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s", # 日志的格式 datefmt=" %Y-%

大帅的博客 1044

北斗三号PPP-B2b信号实战指南:从接收机配置到精度验证全流程

本文提供了北斗三号PPP-B2b信号从硬件配置到数据处理的全流程实战指南。详细解析了信号特性、接收机关键参数设置,并以飞纳接收机和Mass软件为例,演示了数据解算与精度验证方法。通过覆盖中国多地区的联调测试案例,验证了PPP-B2b服务可实现分米级实时定位精度,为无网络地区高精度应用提供了可靠解决方案。

nn3456的博客 551

工业模型导入Unity实战:从ProE/SolidWorks到实时渲染的完整流程

在工业仿真、数字孪生和VR/AR应用开发中,将高精度工程模型导入实时渲染引擎是一个常见的技术挑战。其核心原理在于参数化工程软件与实时渲染引擎的数据结构差异:前者基于精确的B-rep边界表示和特征树,后者依赖轻量化的三角网格与材质贴图。这一转换的技术价值在于实现工程数据的可视化与交互化,为产品展示、虚拟培训和工厂仿真等应用场景提供基础。通过数据翻译与优化流程,特别是利用3ds Max或Blender作为中转站进行网格优化与UV展开,能够有效解决模型破面、材质丢失和性能问题。本文聚焦于ProE(Creo)和So

weixin_33050117的博客 344

Python日志处理(引用logging模块)

Python日志处理 文章目录Python日志处理一. 日志1. 日志的作用2. 日志级别3.日志的流程4. 日志输出格式5. 日志功能的实现二. logging模块简介1. logging模块的日志级别2. logging模块的使用方式介绍logging模块定义的模块级别的常用函数logging模块的四大组件这些组件之间的关系描述:3. logging模块基本使用4. logging模块定义的...

xbean1028的博客 9920

【QGIS入门实战精品教程】1.2:QGIS与ArcGIS的区别和联系

以下是GISGeography官方给出的两者之间的27点比较(译): 官方网址:https://gisgeography.com/qgis-arcgis-differences/ 1.QGIS容纳更多的数据格式 ArcGIS没有支持所有的数据格式,毫无疑问,QGIS在处理各种类型的数据时非常顺手,QGIS在数据格式方面是个多面手,在使用数据方面是它的长处。 QGIS使用GDAL/OGR库来读取和写入地理信息数据格式,支持超过70种矢量格式。QGIS一开始就是为了与PostGIS协作而诞生的,而支持的名单.

智慧空间实验室 2040

Python日志处理(logging模块介绍)

logging模块是Python的一个标准库模块,由标准库模块提供日志记录API的关键好处是所有Python模块都可以使用这个日志记录功能。第一种方式是使用logging提供的模块级别的函数。第二种方式是使用Logging日志系统的四大组件其实,logging所提供的模块级别的日志记录函数也是对logging日志系统相关类的封装而已。logging模块定义的模块级别的常用函数函数说明创建一条严重级别为DEBUG的日志记录创建一条严重级别为INFO的日志记录。

ranxirui8580的博客 1496

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

python日志处理——logging模块

文章目录1. logging配置记录日志2. logging日志模块组件2.1 Logger类2.2 Handler类2.3 Formater类2.4 Filter类3. logging日志处理流程4. logging日记处理例子 1. logging配置记录日志 logging.basicConfig该函数可接收的关键字参数如下: example1:经过配置格式的日志输出 import logging LOG_FORMAT = "%(asctime)s - %(levelname)s - %(l

Clichong 741

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Python之日志处理(logging模块)

Python之日志处理(logging模块) 本节内容 日志相关概念 logging模块简介 使用logging提供的模块级别的函数记录日志 logging模块日志流处理流程 使用logging四大组件记录日志 配置logging的几种方式 向日志输出中添加上下文信息 参考文档 一、日志相关概念 日志是一种可以追踪某些软件运行时所发生事件的...

人生需要曲折和转折 4340

Python之日志处理 logging模块

Python之日志处理(logging模块) 本节内容 日志相关概念 logging模块简介 使用logging提供的模块级别的函数记录日志 logging模块日志流处理流程 使用logging四大组件记录日志 配置logging的几种方式 向日志输出中添加上下文信息 参考文档 一、日志相关概念 日志是一种可以追踪某些软件运行时所发生事件的...

diandian1636的博客 167

Python日志处理:logging模块详解,从零基础到精通,收藏这篇就够了!_python logging 使用教程

大家好,今天我要和大家聊聊Python中的日志处理。还在用print调试代码吗?或者遇到线上问题却不知道出了什么状况?这就说明你需要好好学习一下日志处理了!Python的logging模块是一个强大的日志框架,今天我就带大家掌握这个必备技能。 运行后你会看到类似这样的输出: 2. 配置日志输出到文件 在实际项目中,我们通常需要将日志保存到文件中: 3. 创建自定义的Logger 在大型项目中,我们通常需要创建多个Logger来分别处理不同模块的日志: 4. 日志轮转 当日志文件变得太大时,我们需要进行日志

小司机的奥拓 1546

python日志处理之logging模块

【代码】python日志处理之logging模块。

dynine的博客 126

python 日志处理 logging模块 logging中所有的 handler 处理器 总结

logging中可以使用的handler主要包括: handler名称 位置 作用 StreamHandler logging.StreamHandler 日志输出到流,可以是sys.stderr,sys.stdout或者文件 FileHandler logging.FileHandler 日志输出到文件 BaseRotatingHandler logging.handlers.BaseRotatingHandler 基本的日志回滚方式 Ro

Ximerr的博客 2245

Python 的 logging 模块(三)使用日志处理流程配置

一、介绍四大组件 日志处理流程中,包含了logging模块的四大组件,分别是: 组件名称 对应类名 功能描述 日志器 Logger 提供了应用程序可一直使用的接口 处理器 Handler 将logger创建的日志记录发送到合适的目的输出 过滤器 Filter 提供了更细粒度的控制工具来决定输出哪条日志记录,丢弃哪条日志记录...

xiaoyu_wu的博客 342

【python】logging模块——日志处理

1.python中logging模块的基本使用方法

Zhang_Chen_的博客 405
上一篇: Python-- concurrent包(异步并行任务编程模块)
下一篇: Python -- 网络编程(Socket介绍)
鹿夏
博客等级 码龄8年 24粉丝 105原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值