python中的logging
Ⅰ python程序中logging怎么用
简单将日志打印到屏幕:
[python] view plain
import logging
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
输出:
WARNING:root:warning message
ERROR:root:error message
CRITICAL:root:critical message
可见,默认情况下Python的
logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级
CRITICAL > ERROR > WARNING > INFO > DEBUG >
NOTSET),默认的日志格式为日志级别:Logger名称:用户输出消息。
灵活配置日志级别,日志格式,输出位置
[python] view plain
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename='/tmp/test.log',
filemode='w')
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
查看输出:
cat /tmp/test.log
Mon, 05 May 2014 16:29:53 test_logging.py[line:9] DEBUG debug message
Mon, 05 May 2014 16:29:53 test_logging.py[line:10] INFO info message
Mon, 05 May 2014 16:29:53 test_logging.py[line:11] WARNING warning message
Mon, 05 May 2014 16:29:53 test_logging.py[line:12] ERROR error message
Mon, 05 May 2014 16:29:53 test_logging.py[line:13] CRITICAL critical message
可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger(后边会讲解具体概念)的日志级别
stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
format参数中可能用到的格式化串:
%(name)s Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(mole)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s用户输出的消息
Ⅱ python 中 logging.info是干吗的
logging是python的日志库,是一个类
info是logging的一个属性
logging.info是输出日志的信息
logging.info('输出信息')
Ⅲ 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 logging打印日志混乱问题
解决办法如下:
多么痛的领悟,困扰了这么久的问题其实就是一个参数配置错了。
fileMode:表示日志文件的打开方式。w-直接写,使用这个配置当系统重启的时候日志会清空,一个进程打开后其他进程是无法使用的;a-尾部追加,大家都可以打开往文件结尾进行追加写入。
本人主语言是java,转到python后日志这块踩了几个坑。再说说另外一个坑,就是异常堆栈的打印问题,在java中logger是可以使用error直接打印出来的。在python中error跟其他日志记录方法没太大差别,是无法打印异常堆栈的,打印堆栈请使用 logger.exception("异常说明", e) 。
Ⅳ 在 python 项目中如何记录日志
写本文的目的是我在写 python 项目的时候需要记录日志,我忘记怎么处理了,每次都需要去网上查一遍, 好记性不如烂笔头 , 这里把查阅的内容记录下来,方便以后查找。
python 项目中记录日志,可以使用 logging 模块,logging 模块定义的函数和类为应用程序和库的开发实现了一个灵活的事件日志系统。logging 模块是Python的一个标准库模块,由标准库模块提供日志记录API的关键好处是所有Python模块都可以使用这个日志记录功能。所以,你的应用日志可以将你自己的日志信息与来自第三方模块的信息整合起来。
在 __init__.py 文件中做如下配置:
控制台输出日志如下:
参考文档
https://www.cnblogs.com/yyds/p/6901864.html
Ⅵ 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和handler到底是个什么鬼
最近的任务经常涉及到日志的记录,特意去又学了一遍logging的记录方法。跟java一样,python的日志记录也是比较繁琐的一件事,在写一条记录之前,要写好多东西。典型的日志记录的步骤是这样的:
创建logger
创建handler
定义formatter
给handler添加formatter
给logger添加handler
写成代码差不多就是酱婶的(这个是照别的网页抄的,参考附注):
1 import logging
2
3 # 1、创建一个logger
4 logger = logging.getLogger('mylogger')
5 logger.setLevel(logging.DEBUG)
6
7 # 2、创建一个handler,用于写入日志文件
8 fh = logging.FileHandler('test.log')
9 fh.setLevel(logging.DEBUG)
10
11 # 再创建一个handler,用于输出到控制台
12 ch = logging.StreamHandler()
13 ch.setLevel(logging.DEBUG)
14
15 # 3、定义handler的输出格式(formatter)
16 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
17
18 # 4、给handler添加formatter
19 fh.setFormatter(formatter)
20 ch.setFormatter(formatter)
21
22 # 5、给logger添加handler
23 logger.addHandler(fh)
24 logger.addHandler(ch)
之后才可以正式的开始记录日志。Java里面的java.util.Logging类差不多也是这样,代码还要更复杂一点。Golang的日志相对
写法简单一些,不过没有什么格式,系统记录一条时间,内容格式完全自己手画。第三方的日志库倒是没有接触过,像Java的Log4j,Golang的
log4go和seelog等等,不知道用起来会不会简单一点。我一直都记不住这些,因为不太理解logger和handler为什么要这样写。一直到这
次任务中出现的在我看来相当“诡异”的bug,才深入理解了一下。
我的任务是这样的,要做一个日志切割的工具,按天将日志分割开,即每天0点产生一个新日志,将旧日志改名。并且,将超过3个月的日志删除掉,以保证磁盘空间不会被log占满。程序要求可以切割多个目录中的不同日志,具体路径由json中配置。
这里用到了logging.handlers类中的TimedRotatingFileHandler方法,用以获得一个handler。大概的写法为:
1 logger = logging.getLogger() #获得logger
2 handler = logging.handlers.TimedRotatingFileHandler(logfile, 'S', 1, 0) #切割日志
3 handler.suffix = '%Y%m%d' #切割后的日志设置后缀
4 logger.addHandler(handler) #把logger添加上handler
5 logger.fatal(datetime.datetime.now().strftime('%Y-%m-%d')) #在新日志中写上当天的日期
这里我没有设置level和formatter。因为只是分割,对新日志没有什么影响。TimedRotatingFileHandler函数的方
法见附注,或查看python的源码,这个函数是python写的,可以找到定义。这里我使用的是每秒生成一个新的日志文件,之后用Crontab在每天
0点调度,然后用for循环处理json中的每一个日志文件。
但是奇怪的是,每次运行程序,第一个切割的日志生成一个分割后的文件,而后面的都生成两个新日志。百思不得其解。后检查代码觉得,可能是程序中设置
的时间太短了,每秒生成一个文件,有可能一秒钟处理不完,就生成了两个。虽然这个说法没有什么科学根据,但是还是把
TimedRotatingFileHandler中的第三个参数改成了60,即每60秒生成一个文件。完成,静静的等待crontab到时间。
Ⅷ python logging继承关系
这篇文章主要解析python logging模块不同logger间日志级别的继承关系,以及日志输出的机制。
在python的logging模块中,通过 logging.getLogger() 函数可以获取到指定的logger,如果没有指定参数, 那么返回的是root logger. 通过指定不同的logger名称,这个函数可以返回指定的logger.这里,logger名字 本身体现了logger的继承关系,它通过"."分隔父logger和子logger,可以存在很多个".",他们一路继承下来。
如"a.b"这个logger存在一个父logger"a", 而"a"则从root logger继承而来。如下图所示:
每个logger下面可能存在0个或多个handler,handler实现日志的输出,每个handler对应一个输出目标。 通过配置多个handler,可以实现同时输出到文件,控制台的功能。 同时,每个handler可以定制日志级别,从而使得某些日志级别可以只输出到文件中,而不输出到控制台。
每个logger都可以设置日志级别,如果没有设置,默认是NOSET。当logger的日志级别是NOSET时,它会按照继承关系向上层获取日志级别, 直到日志级别不是NOSET,或达到root logger为止。如以上关系,
这个机制在 官方文档setLevel 中有详细介绍。
logger中,有一个字段 propagate ,这个字段用于控制是否 继承父logger的handler,默认是继承。
当这个选项打开时,logger除了将日志写入自身的handler外,还会将日志写入祖先的handler中。
假设我们往a.b这个logger写入一条日志,其过程如下:
这里需要注意的是,logger的日志级别用于在入口处过滤,handler用于出口处过滤,在propagate的时候,已经过了输入阶段,到达输出阶段, 不需要再判断上层logger的日志级别,只判断handler的级别是否满足。
转自: https://lisongmin.github.io/python-logging-inherit/
Ⅸ Python 中 logging 模块使用详情
在实际应用中,日志文件十分重要,通过日志文件,我们知道程序运行的细节;同时,当程序出问题时,我们也可以通过日志快速定位问题所在。在我们写程序时,也可以借助 logging 模块的输出信息来调试代码。
但是很多人还是在程序中使用print()函数来输出一些信息,比如:
这样用的话缺点很明显,当程序写好运行时,我们要把这些print()函数删掉,在简单的的程序中用还行,当程序比较复杂时,这个办法很低效。
如果使用 logging 模块,看看效果
运行结果如下:
你也许会问,这和 print() 函数有什么区别呢?区别就在于,logging模块可以通过改变level来控制一些语句是否被输出,比如当我们把level改成DEBUG级别:
得到输出如下:
logging 模块是python自带的一个包,因此在使用的时候,不必安装,只需要import即可。有5个level,分别是debug,主要是查看一下程序运行的信息,一般是调试程序要看的信息;info,是我们看程序是否如预料执行的信息;warn,意料之外的,但是不影响程序运行; error 和 critical 就是一些比较严重的问题,会影响程序运行。默认leval是warn,这个时候debug级别和info级别就不会被输出到日志里了。如果想要看到这些信息,就需要进行一些设置。
我们主要调用 basicConfig(***kwargs*) 这个函数对 logging 进行设置。
常用的参数如下:
我们通过调整format,可以输出我们想要的格式,比如:
结果是:
这就是在 format 参数中设置了时间的,所以得到了时间,我们可以输出多种想要的信息
总结:
本文主要介绍了 logging 模块的基础用法,除非是自己写的小脚本中我们使用print()函数,其他情况下最好还是用logging模块来打印信息,输出日志吧。
Ⅹ python的logging模块格式化输出到控制台、文件
logger提供了应用程序可以直接使用的接口;
handler将(logger创建的)日志记录发送到合适的目的输出;
filter提供了细度设备来决定输出哪条日志记录;
formatter决定日志记录的最终输出格式。
控制台彩色显示用到colorama模块
修改Fore.WHITE即可修改相应的颜色