python 日志

一、为什么使用日志 logging

通过记录日志,可以了解系统、程序的运行情况;某些情况下,日志还可以记录用户的操作行为、类型爱好等可以用来分析。日志可以在程序发现问题后让开发人员或运维人员快速定位问题所在。总而言是,日志在开发调试、定位故障、了解程序运行情况等方面发挥重要作用。

二、日志输出形式

  1. 输出到控制台,适合开发阶段
import logging

logging.info('it is start !')
logging.warning('it is run ?')

运行以上程序你只会看到
WARNING:root:it is run ?
这是因为 python 默认的输出日志等级为 WARNING, 而 INFO的等级低于WARNING,被过滤不进行输出。

  1. 写入磁盘文件,适合生产阶段
import logging

logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.debug('this is debug ')
logging.info('this is info')
logging.warning('this is warning')

由于设置了level=logging.DEBUG,所以三条日志消息都会写入日志文件中,filename='example.log'定义了日志文件位置,这里使用了相对路径。

三、什么时候使用日志

print 比较适合命令行测试或者一下代码片段,而当你准备开发一个程序或者完整的项目的时候就应该使用日志。

你想要执行的任务 此任务的最好的工具
对于命令行或程序的应用,结果显示在控制台 print()
在对程序的普通操作发生时提交事件报告(比如:状态监控和错误调查) logging.info() 函数
有诊断目的,需要详细输出信息时使用 logging.debug() 函数
提出一个警告信息基于一个特殊的运行时事件 warnings.warn() 位于代码库中,该事件是可以避免的,需要修改客户端应用以消除告警;logging.warning() 不需要修改客户端应用,但是该事件还是需要引起关注
报告错误而不引发异常(如在长时间运行中的服务端进程的错误处理) logging.error(), logging.exception()logging.critical() 分别适用于特定的错误及应用领域

四、日志等级

日志功能应以所追踪事件级别或严重性而定。各级别适用性如下(以严重性递增):

级别 何时使用
DEBUG 细节信息,仅当诊断问题时适用。
INFO 确认程序按预期运行
WARNING 表明有已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行
ERROR 由于严重的问题,程序的某些功能已经不能正常执行
CRITICAL 严重的错误,表明程序已不能继续执行

默认的级别是WARNING,意味着只会追踪该级别及以上的事件,除非更改日志配置。

五、对日志进行设置 basicConfig()

使用logging.basicConfig(**kwargs)可以对日志进行设置,如上设置日志的输出模式、日志记录等级。有以下可选参数:

格式 描述
filename 指定使用指定的文件名而不是StreamHandler,将创建FileHandler,使日志输出到文件。
filemod 如果指定了filename,则在此处指定 open 打开文件的读写模式。默认为'a',也就是在文件末尾追加。(一般使用默认的'a'就可以)
format 使用指定的格式字符串作为处理程序。
datefmt 使用指定的日期/时间格式
style 指定格式化字符串的风格,可使用'%''{''$',默认使用'%'
level 指定日志记录的(最低)级别
stream 使用指定的流初始化StreamHandler。请注意,此参数与filename不兼容- 如果两者都存在,则引发ValueError。
handlers 如果指定,则被添加到根记录器。任何没有格式化的处理程序都将被分配在此函数中创建的默认格式化程序。请注意,此参数与filename或stream不兼容- 如果两者都存在,则引发ValueError。

详解
1)filename,如果指定 filename ,则认为是将日志输出到磁盘文件(还可以使用 stream 将日志输入到,使用流处理,这里不介绍 流处理 相关内容;两者不兼容,一个日志处理器只能采用一种模式)

2)filemod,指定 open 打开文件的读写模式。一般使用默认的追加模式filemod = 'a',这时候对程序运行3次,则日志会累计3次(输出到指定文件中);如果使用filemod = 'w',则打开日志发现只记录了一次,这是因为后续的日志会覆盖前面的日志。

3)format,格式日志字符串

# test.py
import logging

logging.basicConfig(level=logging.DEBUG,
    format = '%(asctime)s - %(levelname)s - %(message)s - %(lineno)d'
)
logging.info('ok !')

你将会看到打印以下内容

>>>2019-08-05 10:22:40,817 - INFO - ok ! - 6

其中 2019-08-05 10:22:40,817 是我们设置的 %(asctime)s,也就是格式化时间
INFO 是 %(levelname)s,日志等级
ok ! 是 %(message)s,logging 输出信息
6 是%(lineno)d , 日志输出所在行。
-是我们自己设置的分割符,可以根据自己的习惯设定,例如

format = '[%(asctime)s] [%(filename)s]  [%(message)s]  [%(lineno)d]'

这里介绍一些常用的格式化选项,更多可以看 python 日志模块

格式 描述
%(asctime)s 格式化时间(例:2019-08-05 10:36:08,504)
%(created)f 时间戳(例:1564972568.504417)
%(msecs)d 日志输出的时间 毫秒部分(例:504)
%(filename)s 日志输出所在文件名(例:test.py
%(module)s 模块名称,filename 输出为test.py module输出为test,不带.py
%(pathname)s 日志输出所在完整路径(例:/Users/wuyaa/PycharmProjects/lern_p3/test.py
%(funcName)s 日志输出所在方法名称
%(levelname)s 文本日志记录级别消息,('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
%(levelno)s 对于消息数字记录级别(DEBUG,INFO, WARNING,ERROR, CRITICAL)
%(lineno)d 发出日志记录调用的源码行号(如果可用)。
%(message)s 记录的消息,(也就是 logging.info('this is a message') 等记录的消息)
%(name)s 日志记录器的名称(例:root表示是根记录器 )
%(process)d 进程ID(如果可用)。
%(processName)s 进程名称(如果可用)
%(thread)d 线程ID(如果可用)。
%(threadName)s 线程名称(如果可用)。

4)datefmt
datefmt 是作为%(asctime)s的补充,在 format 设置格式化时间后,可以进行更精准的格式输出,更多可以参考 time.strftime

格式 描述
%A 本地化的星期中每日的完整名称。
%B 本地化的月完整名称。
%Y 十进制数表示的带世纪的年份。
%m 十进制数 [01,12] 表示的月。
%d 十进制数 [01,31] 表示的月中日。
%H 十进制数 [00,23] 表示的小时(24小时制)。
%M 十进制数 [00,59] 表示的分钟
%S 十进制数 [00,61] 表示的秒。
%Z 时区名称(如果不存在时区,则不包含字符)。
# test.py
import logging

def main():
    logging.basicConfig(level=logging.DEBUG,
                        format='[%(asctime)s]  [%(funcName)s]  [%(message)s]  [%(lineno)d]',
                        datefmt='%Y/%m/%d %I:%M:%S')
    logging.info('ok')

if __name__ == '__main__':
    main()

输出如下:

>>>[2019/08/05 11:25:18]  [main]  [ok]  [10]

5)style
格式化字符串的风格,使用默认值即可,无需改动

六、从多个模块记录日志

如果你的程序包含多个模块,你并不需要在每个模块引进 logging 后都设置进行配置,而是在主函数入口设置一次即可。

# mylib.py
import logging

def do_something():
    logging.info('Doing something')
# myapp.py
import logging

# 具体导入时根据你自己模块的路径,我这里是根据我自己的运行环境,最好从模块 根路径 导入,而不要使用相对路径
from learn_test.log.mylib import do_something

def main():
    logging.basicConfig(level=logging.INFO,
        format='[%(asctime)s]  [%(funcName)s]  [%(message)s]  [%(lineno)d]',
        datefmt='%Y/%m/%d %I:%M:%S')

    logging.info('Started')
    do_something()
    logging.info('Finished')

if __name__ == '__main__':
    main()

在程序入口设置的basicConfig,在 mylib.py 的do_something() 函数中也会起作用

七、日志进阶 记录器Logger

未完待续......

参考文件
https://docs.python.org/zh-cn/3.7/howto/logging.html
https://docs.python.org/zh-cn/3.7/library/logging.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容