导航:首页 > 编程语言 > python多进程写日志

python多进程写日志

发布时间:2023-03-26 02:56:35

㈠ 多进程环境python logging打印日志混乱问题

解决办法如下:

多么痛的领悟,滑腔困扰了这么久的问题其实就是一个参数配置错了。
fileMode:表示日志山让侍文件的打开方式。w-直接写,使用这个配置当系统重启的时候日志会清空,一个进程打开后其他进程是无法使用的;a-尾部逗吵追加,大家都可以打开往文件结尾进行追加写入。

本人主语言是java,转到python后日志这块踩了几个坑。再说说另外一个坑,就是异常堆栈的打印问题,在java中logger是可以使用error直接打印出来的。在python中error跟其他日志记录方法没太大差别,是无法打印异常堆栈的,打印堆栈请使用 logger.exception("异常说明", e) 。

㈡ python 多进程

基于官方文档:
https://docs.python.org/zh-cn/3/library/multiprocessing.html
日乐购,刚才看到的一个博客,写的都不太对,还是基于官方的比较稳妥
我就是喜欢抄官方的,哈哈

通常我们使用Process实例化一个进程,并调用 他的 start() 方法启动它。
这种方法和 Thread 是一样的。

上图中,我写了 p.join() 所以主进程是 等待 子进程执行完后,才执行 print("运行结束")
否则就是反过来了(这个不一定,看你的语句了,顺序其实是随机的)例如:

主进加个 sleep

所以不加join() ,其实子进程和主进程是各干各的,谁也不等谁。都执行完后,文件运行就结束了

上面我们用了 os.getpid() 和 os.getppid() 获取 当前进程,和父进程的id
下面就讲一下,这两个函数的用法:
os.getpid()
返回当前进程的id
os.getppid()
返回父进程的id。 父进程退出后,unix 返回初始化进程(1)中的一个
windows返回相同的id (可能被其他进程使用了)
这也就解释了,为啥我上面 的程序运行多次, 第一次打印的parentid 都是 14212 了。
而子进程的父级 process id 是调用他的那个进程的 id : 1940

视频笔记:
多进程:使用大致方法:

参考: 进程通信(pipe和queue)

pool.map (函数可以有return 也可以共享内存或queue) 结果直接是个列表

poll.apply_async() (同map,只不过是一个进程,返回结果用 xx.get() 获得)

报错:

参考 : https://blog.csdn.net/xiemanR/article/details/71700531

把 pool = Pool() 放到 if name == " main ": 下面初始化搞定。
结果:

这个肯定有解释的

测试多进程计算效果:
进程池运行:

结果:

普通计算:

我们同样传入 1 2 10 三个参数测试:

其实对比下来开始快了一半的;
我们把循环里的数字去掉一个 0;
单进程:

多进程:

两次测试 单进程/进程池 分别为 0.669 和 0.772 几乎成正比的。
问题 二:
视图:
post 视图里面

Music 类:

直接报错:

写在 类里面也 在函数里用 self.pool 调用也不行,也是相同的错误。

最后 把 pool = Pool 直接写在 search 函数里面,奇迹出现了:

前台也能显示搜索的音乐结果了

总结一点,进程这个东西,最好 写在 直接运行的函数里面,而不是 一个函数跳来跳去。因为最后可能 是在子进程的子进程运行的,这是不许的,会报错。
还有一点,多进程运行的函数对象,不能是 lambda 函数。也许lambda 虚拟,在内存??

使用 pool.map 子进程 函数报错,导致整个 pool 挂了:
参考: https://blog.csdn.net/hedongho/article/details/79139606
主要你要,对函数内部捕获错误,而不能让异常抛出就可以了。

关于map 传多个函数参数
我一开始,就是正常思维,多个参数,搞个元祖,让参数一一对应不就行了:

报错:

参考:
https://blog.csdn.net/qq_15969343/article/details/84672527
普通的 process 当让可以穿多个参数,map 却不知道咋传的。
apply_async 和map 一样,不知道咋传的。

最简单的方法:
使用 starmap 而不是 map

结果:
子进程结束
1.8399453163146973
成功拿到结果了

关于map 和 starmap 不同的地方看源码

关于apply_async() ,我没找到多参数的方法,大不了用 一个迭代的 starmap 实现。哈哈

关于 上面源码里面有 itertools.starmap
itertools 用法参考:
https://docs.python.org/zh-cn/3/library/itertools.html#itertool-functions

有个问题,多进程最好不要使用全部的 cpu , 因为这样可能影响其他任务,所以 在进程池 添加 process 参数 指定,cpu 个数:

上面就是预留了 一个cpu 干其他事的

后面直接使用 Queue 遇到这个问题:

解决:
Manager().Queue() 代替 Queue()

因为 queue.get() 是堵塞型的,所以可以提前判断是不是 空的,以免堵塞进程。比如下面这样:
使用 queue.empty() 空为True

㈢ python中更优雅的记录日志

在以往我们使用日志,更多的是使用 python 自带的 logging 模块态大迅,它可以设置错误等级、输出方式等。

但使用方式相对比较复杂,想要更好的使用需要如 log4net 一样单独配置,这在 python 中感觉不是很优雅。

下面介绍一个 python 库: loguru 。 guru 是印度语中大师的意思, loguru 直译就是“日志大师”。

如图 logging 一样, loguru 也有定义日志等级。不同的日志等级,输出效果也不一样(默认的等级由低到高是 DEBUG 、 INFO 、 WARNING 、 ERROR 、 CRITICAL ,也可以自己使用 level 函数定义)。

类似 logging 中的 logger.addHandler ,loguru统一使用 add 函数来管理格式、文件输出、过滤等操作,它提供了许多参数来实现 logger.addHandler 中的配置更加简单方便。

其中 sink 是最重要的参数,可以传入不同的数据类型。传入文件路径、文件句柄、 sys.stderr 、甚至 logging 模块的 Handler 如 FileHandler 、 StreamHandler 等,这样就可以快速实现自定义的 Handler 配置。

通过给 remove 方法传递 add 方法返回的对象, 可以帆此删除 add 方仿槐法添加的 sink ,这里的 remove 并不是删除 test2.log 文件,而是停止向该文件输出日志,需要需要继续记录日志则需要重新 add 日志文件。

用 rotation 、 retention 、 compression 进行日志窗口、更新、压缩管理。

支持控制台输出添加颜色, 除了基础色, loguru 甚至允许16进制、RGB格式的颜色值和加粗、下划线等样式。

使用装饰器 @logger.catch 可以和 logging 一样使用 logger.exception 函数来记录异常信息。

使用 exception 方法输出的异常信息包含堆栈信息和当前变量的值,方便问题定位。

使用 serialize 可以将日志转换为 JSON 格式, enqueue 可以保证多线程、多进程安全。

修改时间格式。

㈣ 在 python 项目中如何记录日志

写本文的目的是我在写 python 项目的时候需要记录日志,我忘记怎么处理了,每次码逗竖都需要去网上查一遍, 好记性不如烂笔头 , 这里把查阅的内容记录下来,方便以后查找。

python 项目中记录日志,可以使用 logging 模块,logging 模块定义的函数和类为应用程序和指岁库的开发实现了一个灵活的事件日志系统。logging 模块是Python的一个标准库模块,由标准库模块提供日志记录API的关键好处是所有Python模块都可以使用这个日志记录功能。所以,你的应用日志可以将你自己的日志信息与来自第三方模块迟大的信息整合起来。

在 __init__.py 文件中做如下配置:

控制台输出日志如下:

参考文档
https://www.cnblogs.com/yyds/p/6901864.html

㈤ python多进程存数据不改变顺序

你的问题太模糊了。我先从常见的错误说,然后再从相对从大的方面来描述。

进程挂掉可能是什么原因?

一方面是程序可能有逻辑错误,导致了诸如下标越界,数据异常等问题。

另一方面,可能是系统原因,比如代码质量一般,系统资源消耗厉害,进程退出。

还有可能是上下游服务问题,比如 MySQL 等服务异常,上游 API 异常,配置错误。

简单说了下各种可能的异常,但对一个项目而言,天下问题千千万,不可能有一条完美的准则。

遇到问题,通常要从几步出发,从排查出错原因、寻找解决方案和如何预防出发。

排查错误的原因,这是最重要的一步,只有对症下药才能解决问题。

首先确认下是否搏旅容易复现的问题,容易复现的话,通常会给出错误信息。然后,我们只要在开发时调试下就好了,常见的调试方法有 print 打印来观察问题,或者是使用一些 debug 调试工具,我相信你会用。print 的特点是简单好用,但每次都有修改代码,比较繁琐。而调试工具就比较方便,看的信息会比较全,一些 IDE 都集成了调试工具。

对于不容易复现的问题,可以通过记录日志的方式排查。有人会说,记录日志是资源消耗,曾经我也怎么想过。但对于现在的硬件配置而已,记录日志的成本是非常小的,一个好像的项目肯定是集成日志的,不然就太 low 逼了,我可不敢用。

寻找解决方案,这一步需要基于前面诊断出的结果进行排查。

一个简单的案例。比如,提示 MySQL 连接数过多,什么情况可能导致这个问题?是 MySQL 配置的连接数本身就很少,还是程序设计不合理导致连接无法正确复用,亦或是业务量真的大了,当前最大连尘巧接数无法承受呢。每种情况的处理方式都不同。

如何预防问题,我主要想学详细的日志,和增加一些恢复机制。

详细的日志就不说了,异常要记得捕获,并且记录发生异常的原因,这一步对排查问题非常有帮助。

另外,不是所派银键有的异常都应该立刻退出进程,如果不是一些非常严重的错误,通过日志提示下,程序还可以继续工作。不过,有些异常还是要做一些修复处理,比如数据库连接断开,可尝试重新连接,上游系统服务异常,可以执行多次调用,而不是直接退出。

就简单说这么多吧!如果有些地方讲的不是很好,见谅。欢迎评论补充,谢谢!

㈥ Loguru:Python 日志终极解决方案

日志的作用非常重要,日志可以记录用户的操作、程序的异常,还可以为数据分析提供依据,日志的存在意义就是为了能够在程序在运行过程中记录错误,方便维护和调试,能够快速定位出错的地方,减少维护成本。每个程序员都应该知道,不是为了记录日志而记录日志,日志也不是随意记的。要实现能够只通过日志文件还原整个程序执行的过程,达到能透明地看到程序里执行情况,每个线程、每个过程到底执行到哪的目的。日志就像飞机的黑匣子一样,应当能够复原异常的整个现场乃至细节!

最常见的是把输出函数 print() 当作日志记录的方式,直接打印各种提示信息,常见于个人练习项目里,通常是懒得单独配置日志,而且项目太小不需要日志信息,不需要上线,不需要持续运行,完整的项目不推荐直接打印日志信息,现实中也几乎没有人这么做。

我们可以在不少小项目里面看到作者自己写了一个日志模板,通常利用 print() 或者 sys.stdout 稍微封装一下即可实现简单的日志输出,这里的 sys.stdout 是 Python 中的标准输出流, print() 函数是对 sys.stdout 的高级封装,当我们在 Python 中打印对象调用 print(obj) 时候,事实上是调用了 sys.stdout.write(obj+'\n') , print() 将内容打印到了控制台,然后追加了一个换行符 \n 。

自写日志模板适合比较小的项目,可以按照自己的喜好编写模板,不需要太多复杂配置,方便快捷,但是这种记录日志的方式并不是很规范,有可能你自己觉得阅读体验不错,但是别人在接触你的项目的时候往往需要花费一定的时间去学习日志的逻辑、格式、输出方式等,比较大的项目同样不推荐这种方法。

一个简单的自写日志模板举例:

日志模板 log.py:

调用日志模块:

日志输出:

在一个完整的项目中,大多数人都会引入专门的日志记录库,而 Python 自带的标准库 logging 就是专门为日志记录而生的,logging 模块定义的函数和类为应用程序和库的开发实现了一个灵活的事件日志系统。由标准库模块提供日志记录 API 的关键好处是所有 Python 模块都可以使用这个日志记录功能。所以,你的应用日志可以将你自己的日志信息与来自第三方模块的信息整合起来。

logging 模块虽然强大,但是其配置也是比较繁琐的,在大型项目中通常需要单独初始化日志、配置日志格式等等,K哥在日常使用中通常都会对 logging 做如下的封装写法,使日志可以按天保存,保留15天的日志,可以配置是否输出到控制台和文件,如下所示:

输出日志:

它在控制台中是这样的:

当然,如果你不需要很复杂的功能,希望简洁一点,仅仅需要在控制台输出一下日志的话,也可以只进行简单的配置:

对于 logging 模块,即便是简单的使用,也需要自己定义格式,这里介绍一个更加优雅、高效、简洁的第三方模块:loguru,官方的介绍是:Loguru is a library which aims to bring enjoyable logging in Python. Loguru 旨在为 Python 带来愉快的日志记录。这里引用官方的一个 GIF 来快速演示其功能:

Loguru 仅支持 Python 3.5 及以上的版本,使用 pip 安装即可:

Loguru 的主要概念是只有一个:logger

控制台输出:

可以看到不需要手动设置,Loguru 会提前配置一些基础信息,自动输出时间、日志级别、模块名、行号等信息,而且根据等级的不同,还自动设置了不同的颜色,方便观察,真正做到了开箱即用!

如果想自定义日志级别,自定义日志格式,保存日志到文件该怎么办?与 logging 模块不同,不需要 Handler,不需要 Formatter,只需要一个 add() 函数就可以了,例如我们想把日志储存到文件:

我们不需要像 logging 模块一样再声明一个 FileHandler 了,就一行 add() 语句搞定,运行之后会发现目录下 test.log 里面同样出现了刚刚控制台输出的 debug 信息。

与 add() 语句相反, remove() 语句可以删除我们添加的配置:

此时控制台会输出两条 debug 信息:

而 test.log 日志文件里面只有一条 debug 信息,原因就在于我们在第二条 debug 语句之前使用了 remove() 语句。

Loguru 对输出到文件的配置有非常强大的支持,比如支持输出到多个文件,分级别分别输出,过大创建新文件,过久自动删除等等。 下面我们来详细看一下 add() 语句的详细参数:

基本语法:

基本参数释义:

当且仅当 sink 是协程函数时,以下参数适用:

当且仅当 sink 是文件路径时,以下参数适用:

这么多参数可以见识到 add() 函数的强大之处,仅仅一个函数就能实现 logging 模块的诸多功能,接下来介绍几个比较常用的方法。

add() 函数的 rotation 参数,可以实现按照固定时间创建新的日志文件,比如设置每天 0 点新创建一个 log 文件:

设置超过 500 MB 新创建一个 log 文件:

设置每隔一个周新创建一个 log 文件:

add() 函数的 retention 参数,可以设置日志的最长保留时间,比如设置日志文件最长保留 15 天:

设置日志文件最多保留 10 个:

也可以是一个 datetime.timedelta 对象,比如设置日志文件最多保留 5 个小时:

add() 函数的 compression 参数,可以配置日志文件的压缩格式,这样可以更加节省存储空间,比如设置使用 zip 文件格式保存:

其格式支持: gz 、 bz2 、 xz 、 lzma 、 tar 、 tar.gz 、 tar.bz2 、 tar.xz

Loguru 在输出 log 的时候还提供了非常友好的字符串格式化功能,相当于 str.format() :

输出:

在 Loguru 里可以直接使用它提供的装饰器就可以直接进行异常捕获,而且得到的日志是无比详细的:

日志输出:

在控制台的输出是这样的:

相比 Logging,Loguru 无论是在配置方面、日志输出样式还是异常追踪,都远优于 Logging,使用 Loguru 无疑能提升开发人员效率。本文仅介绍了一些常用的方法,想要详细了解可参考 Loguru 官方文档 或关注 Loguru GitHub 。

㈦ 如何使用Python实现多进程编程

1.Process
创建进程的类:Process([group[,target[,name[,args[,kwargs]]]]]),target表示调用对象,args表示调用对象的位置参数元组。kwargs表示调用对象的字典。name为别名。group实质上不使用。
方法:is_alive()、join([timeout])、run()、start()、terminate()。其中,Process以start()启动某个进程。
属性:authkey、daemon(要通过start()设置)、exitcode(进程在运行时为None、如果为–N,表示被信号N结束)、name、pid。其中daemon是父进程终止后自动终止,且自己不能产生新进程,必须在start()之前设置。

例1.1:创建函数并将其作为单个进程
importmultiprocessing
importtime

defworker(interval):
n=5
whilen>0:
print("Thetimeis{0}".format(time.ctime()))
time.sleep(interval)
n-=1

if__name__=="__main__":
p=multiprocessing.Process(target=worker,args=(3,))
p.start()
print"p.pid:",p.pid
print"p.name:",p.name
print"p.is_alive:",p.is_alive()
结果
12345678p.pid:8736p.name:Process-1p.is_alive:TrueThetimeisTueApr2120:55:122015ThetimeisTueApr2120:55:152015ThetimeisTueApr2120:55:182015ThetimeisTueApr2120:55:212015ThetimeisTueApr2120:55:242015

例1.2:创建函数并将其作为多个进程
importmultiprocessing
importtime

defworker_1(interval):
print"worker_1"
time.sleep(interval)
print"endworker_1"

defworker_2(interval):
print"worker_2"
time.sleep(interval)
print"endworker_2"

defworker_3(interval):
print"worker_3"
time.sleep(interval)
print"endworker_3"

if__name__=="__main__":
p1=multiprocessing.Process(target=worker_1,args=(2,))
p2=multiprocessing.Process(target=worker_2,args=(3,))
p3=multiprocessing.Process(target=worker_3,args=(4,))

p1.start()
p2.start()
p3.start()

print("ThenumberofCPUis:"+str(multiprocessing.cpu_count()))
forpinmultiprocessing.active_children():
print("childp.name:"+p.name+" p.id"+str(p.pid))
print"END!!!!!!!!!!!!!!!!!"
结果
1234567891011ThenumberofCPUis:4childp.name:Process-3p.id7992childp.name:Process-2p.id4204childp.name:Process-1p.id6380END!!!!!!!!!!!!!!!!!worker_1worker_3worker_2endworker_1endworker_2endworker_3

例1.3:将进程定义为类
importmultiprocessing
importtime

classClockProcess(multiprocessing.Process):
def__init__(self,interval):
multiprocessing.Process.__init__(self)
self.interval=interval

defrun(self):
n=5
whilen>0:
print("thetimeis{0}".format(time.ctime()))
time.sleep(self.interval)
n-=1

if__name__=='__main__':
p=ClockProcess(3)
p.start()
注:进程p调用start()时,自动调用run()
结果
12345thetimeisTueApr2120:31:302015thetimeisTueApr2120:31:332015thetimeisTueApr2120:31:362015thetimeisTueApr2120:31:392015thetimeisTueApr2120:31:422015

㈧ Python日志—Python日志模块logging介绍

从事与软件相关工作的人,应该都听过“日志”一词。

日志就是跟踪软件运行时事件的方法,为了能够在程序运行过程中记录错误。

通过日志记录程序的运行,方便我们查询信息,以便追踪问题、进行维护和调试、还是数据分析。

并且各编程语言都形成了各自的日志体系和相应的框架。

日志的作用总结:

首先我们要树立一个观点,那就是“不是为了记录日志而记录日志,日志也不是随意记的”。要实现能够只通过日志文件还原整个程序执行的过程,达到能透明地看到程序里执行情况,每个线程每个过程到底执行结果的目的。日志就像飞机的黑匣子一样,应当能够复原异常的整个现场乃至细节。

在项目中,日志这个功能非常重要,我们要重视起来。

在Python中,使用logging模块来进行日志的处理。

logging是Python的内置模块,主要用于将日志信息进行格式化内容输出,可将格式化内容输出到文件,也可输出到屏幕。

我们在开发过程中,常用print()函数来进行调试,但是在实际应用的部署时,我们要将日志信息输出到文件中,方便后续查找以及备份。

在我们使用日志管理时,我们也可以将日志格式化成Json对象转存到ELK中方便图形化查看及管理。

logging模块将日志系统从高向低依次定义了四个类,分别是logger(日志器)、handler(处理器)、filter(过滤器)和formatter(格式器)。其中由日志器生成的实例将接管原本日志记录函数logging.log的功能。

说明:

我们先来思考下下面的两个问题:

在软件开发阶段或部署开发环境时,为了尽可能详细的查看应用程序的运行状态来保证上线后的稳定性,我们可能需要把该应用程序所有的运行日志全部记录下来进行分析,这是非常耗费机器性能的。

当应用程序正式发布或在生产环境部署应用程序时,我们通常只需要记录应用程序的异常信息、错误信息等,这样既可以减小服务器的I/O压力,也可以避免我们在排查故障时被淹没在日志的海洋里。

那么怎样才能在不改动应用程序代码的情况下,根据事件的重要性或者称之为等级,实现在不同的环境中,记录不同详细程度的日志呢?

这就是日志等级的作用了,我们通过配置文件指定我们需要的日志等级就可以了。

说明:

总结:

开发应用程序时或部署开发环境时,可以使用DEBUG或INFO级别的日志获取尽可能详细的日志信息,可以方便进行开发或部署调试。 应用上线或部署生产环境时,应用使用WARNING或ERROR或CRITICAL级别的日志,来降低机器的I/O压力和提高获取错误日志信息的效率。 日志级别的指定通常都是在应用程序的配置文件中进行指定的。 不同的应用程序所定义的日志等级会有所差别,根据实际需求来决定。

㈨ python 多线程logger问题

因为logging是threadsafe的,但不是process-safe(应该没有这个词儿,只是为了便于理解)的。这段代码就是多个进程共同操作一个日志文件。这种情况下,logging的行为就很难说了。


我测试了一下,日志中大概几百行。而且,可以看到一些顺序错乱现象:

Fri, 08 Aug 2014 01:19:38 logging_in_multithread.py[line:40] theadWorking ERROR 2
FFri, 08 Aug 2014 01:19:36 logging_in_multithread.py[line:40] theadWorking ERROR 11(注意这里的FFri)


把代码这样改:

fornuminrange(processNum):
p=Process(target=processWorking,args=('2',))
processs.append(p)
p.start()
p.join()

还有其他方法,比如:为logging实现一个FileHandler,以使logging在multiple process的环境下也能正常工作。这是我从网上了解到的做法,自己还没实践过。


Python Manual中logging Cookbook中有这么一段话:

Logging to a single file from multiple processes

Although logging is thread-safe, and logging to a single file from multiple threads in a single process is supported, logging to a single file from multiple processes is not supported, because there is no standard way to serialize access to a single file across multiple processes in Python. If you need to log to a single file from multiple processes, one way of doing this is to have all the processes log to a SocketHandler, and have a separate process which implements a socket server which reads from the socket and logs to file. (If you prefer, you can dedicate one thread in one of the existing processes to perform this function.)

这段话中也提出了另外一种解决方案。

㈩ logging:多线程调试时用来代替print和单步调试

当你要写多线程项目时,不免要调试错误,要debug。

一般debug的工具就是打印函数print, 调试工具gdb进行单步调试,但是多线程时,单步调试就很鸡肋了,这时就需要打印日志了

没错,打印日志无疑是调试多线程工程的高效工具了。

在python中开发,就要用到logging日志库了

logging库已经封装好日志需要的基本功能,能够实现在文件里,在命令行等写日志

还能输出日志信息的类型,如debug,warning,error等

细节在这里有所介绍:

https://docs.python.org/3/howto/logging.html

文本介绍一下,第一次使用logging时,要熟悉logging时,需要用一个非常简单的例子

先看一个最简单的隐绝例子:

运行以上代码:

printed out on the console. The INFO message doesn’t appear because the default level is WARNING . The printed message includes the indication of the level and the description of the event provided in the logging call, i.e. ‘Watch out!’. Don’t worry about the ‘root’ part for now: it will be explained later. The actual output can be formatted quite flexibly if you need that; formatting options will also be explained later.

输出结果为:

如果你想每次都在一个新的日志文件中写日志,那么使用filemode='w'参数:

分别在main 函数里,在mylib.py里写日志

运行后的输出:

以上代码会显示:

该 format参数的值

以上代码会显示:

还是该format:

以上代码会输出

如果想自己设定时间的格式:

会这样显示:

logging库中用了模块化的思路,把日志的整体功能用了4个基本的模块来完成:

Loggers,Handlers,Filters,Formatters

其中,Handlers,主要配置将信息写到命令行,还是写到文件里。

Filters,是对信息本身的过滤,决定那些信息不写,那些信息写。

Formatters决定信息输出的格式。比如是否输出时间,是否输出logger本身的名字等,决定那些信息在前,那些信息在后等。

Logger就是Handler,Filter,Formatter配置的一个日志对象了。

下面我们逐个说一下这4个类:

它有三个功能,1 提供分级日志的输出,比如 WARNING,ERROR,INFO等不同等级。2. 它可以决定哪些信息输历顷出,哪些信息不输出。3 它可以将一条信息发给命令行和文件,可以把一条信息发给多个handler去处理。

logger 最常用的成员方法大概分两类:配置和信息发送

以下是常用的配置函数:

Logger.setLevel() 设定信息记录的等级。如果一条信息的等级比我们设定的低,那么就不对此条信息进行处理。信息一共分为:DEBUG,INFO,WARNING,ERROR,CRITICAL 五个级别,其中DEBUG是最低的等级,CRITICAL是最高的等级。

Logger.addHandler() 和 Logger.removeHandler(),添加或者删除信息处理器Handler。这个信息处理器就是定义了将日志写入命令行,还是写入文件,或者写入邮件等。

Logger.addFilter() 和 Logger.removeFilter() .添加或者删除信息过滤器Filter。这个信息过滤器,决定了哪些信息不显示。

可以看到,信息过肢携陆滤器,信息处理器,信息等级共同配置了logger.

并不是每个logger你都需要去配置一遍,你可以利用logger的继承机制,只配置父logger.

一旦配置好logger之后,就可以用以下函数来在你自己代码的任意位置来记录日志了。

Logger.debug(),Logger.info(),Logger.warning(),Logger.error()和Logger.critical.这些函数的功能都是建立了日志记录信息,不同的是,函数名字就代表了其建立的日志信息的等级。

Logger.exeception()建立一个与Logger.error()比较相似的信息。但是Logger.exception()是放入一个追踪盏里面的。所以,只有在exception handler处理器中,才能使用它。

Logger.log()发送一个LOG 等级的信息,使用LOG等级的信息稍微繁琐些,因为使用LOG等级可以自定义等级。

getLogger() 返回一个logger的引用,如果指定了名字,那么返回特定名字对应的logger,如果没有指定名字,那就返回一个名字为root的loger的引用名字root,或者你指定的名字是一种级连结构。用同样的名字去调用getLogger(),会得到同样的值。logger的名字也决定了logger在树结构中的层级。例如:这里有一个logger的名字为foo,那么foo.bar,foo.bar.baz,还有foo.bam都是foo的子孙,logger还有一个有效等级level的概念。这个有效等级其实就是决定debug,info,warning等不同类型的消息是否进行记录。因为logger本身有了父子那样的继承关系,所以有效等级level也是可以继承的。如果子logger没有设定了自身的level,那么就把父logger的level继承过来使用。如果子logger本身设定了level,就用自身这个level.如果父logger仍然没有设定level,那就看父logger的父logger,一直这么追述下去,就会追述到root上,所以,我们必须给root设定一个level,或者默认一个level,方便root的子logger去继承。我们给root设定的默认levle为WARNING.如果有些日志的level,相比我们设定的WARNING低,那么它就不会被传递给Handler去处理,就不会被打印出来,或者记录进日志文件。另外logger的属性也是可继承的,所以就只配置一下root logger即可,没有root logger时,只用配置一个相对的那个根logger就行了

handler 信息处理器是负责信息分发给不同的目的地的,这个目的地可能是命令行,也可能是文件,或者邮件。分发时,同样要检查信息本身的等级severity.一个logger可以用addHandler()函数添加0个或者多个handlers。比如有这样一个场景,希望发送所有的log等级的信息到一个log文件内。所有的等级为错误的信息到stdout 标准输出上,发送所有的critical信息到邮件上。这样的场景需要3个不同的处理器,每个处理器负责发送相应等级的信息到相应的目的地。

标准库里包含一些处理器类型,本教程主要使用StreamHandler 和 FileHandler两种信息处理器。

处理器中的成员函数非常少,我们用来配置处理器的成员函数大概有这个几个:

setLevel(),用来设置处理器处理的信息等级。注意到logger中有setLevel(),而处理器中也有setLevel(),也就是说,logger把信息通过信息等级过滤一遍后,logger内的处理器需要根据处理器自身的功能设定,再根据信息等级来过滤一遍。

setFormatter() 为处理器设定一种信心记录的格式Formatter

addFilter() removeFilter()函数添加信息过滤器或者删除信息过滤器的函数。

到这里,我们发现,logger类中,将信息发送到不同的目的地就依赖Handlers实现的,

所有Handler就需要用Formatter和Filter来配置一下。接下来,我们看看Formatter和Filter.

它决定了信息显示的顺序,结构和内容。可以直接操作formatter的相关类,也可以自己继承 formatter类,去完成自己的设定。formatter的构造函数需要3个可选的参数:字符串格式的信息,日期,一个符号。

logging.Formatter.__init__(fmt=None,datafmt=None,style='%')

如果这里没有设定参数,就使用默认参数。对于fmt来说,就显示原来信息,对于datafmt来说,就以年-月-日 时:分:秒的合适显示。

下面的fmt就定义了一个按照 时间-信息等级-信息本身 来记录日志的方法:

这里有三种方法:

写代码配置logging的例子:

运行结果为:

写配置文件配置logging的例子:

代码中所需要的配置文件ogging.conf的具体内容为 :

以上代码的输出为:

显然,配置文件修改起来相对容易很多。

还有更方便的配置方式,使用字典来配置:

运行结果与上面一样。

到这里,基本完成了logging库的比较常用的使用方式。

比如在什么情况下,需要使用一个什么都不做的处理器NullHandler(),

还有关于信息等级的更详细的解释:

以及如何自定义信息等级。

还有关于异常的处理

还有关于信息的,信息都是字符串的。不过你也可以直接把某个类作为信息抛出来,因为类会自动调用其__str__()函数,返回一个类的字符串回来。

还有就是优化性能的一些小技巧

这里就编写expensive_func1 和 expensive_func2 来完成设定数据格式。

以下表格也显示了如何收集运行log的代码文件信息,线程信息,进程信息,处理器信息

以及如何操作才能收集代码文件信息,线程信息,进程信息,以及处理器信息。

我们一般会使用收集代码文件,线程,进程等信息,因为这样大大方便了多线程多进程工程的调试。

阅读全文

与python多进程写日志相关的资料

热点内容
为什么我的世界天空服务器进不去 浏览:260
钉钉直播后的视频如何线上加密 浏览:503
听主的命令 浏览:206
全民上云时代云服务器 浏览:519
iphone不创建id如何下载app 浏览:970
windowsphp扩展安装 浏览:93
emacslinux配置文件 浏览:379
python3在线教程 浏览:114
不小心删文件夹的文件 浏览:480
java获取手机IP 浏览:816
手机rar解压密码获取 浏览:344
程序员被辞退工资怎么处理 浏览:494
恋活的模型没加密 浏览:159
如何把安卓机的微信转移苹果 浏览:583
爬山算法相关题目 浏览:724
vc编程大全 浏览:118
excel表格单列数据加密 浏览:649
给同事的解压话语 浏览:993
linux关闭网卡命令行 浏览:456
史上最漂亮程序员 浏览:771