python日志模块 -- logging

logging模块的四大组件

  • Logger: 对象扮演了三重角色.首先,它暴露给应用几个方法以便应用可以在运行时写log. 其次,Logger对象按照log信息的严重程度或者根据filter对 象来决定如何处理log信息(默认的过滤功能).最后,logger还负责把log信息传送给相关的log handlers。可以通过logging.getLogger(name)获取logger对象,如果不指定name则返回root对象,多次使用相同的name调用getLogger方法返回同一个logger对象。
  • Handler: 对象负责分配合适的log信息(基于log信息的严重 程度)到handler指定的目的地,比如文件,socket等。Logger对象可以用addHandler()方法添加零个或多个handler对象到它自身。一个常见的场景 是,一个应用可能希望把所有的log信息都发送到一个log文件中去,所有的error级别以上的log信息都发送到 stdout,所有critical 的log信息通过email发送。这个场景里要求三个不同handler处理,每个handler负责把特定的log信息发送到特定的地方。
  • Filter: 细致化,选择哪些日志输出
  • Formater: 设置显示格式
%(name)s Logger的名字
%(levelname)s 文本形式的日志级别
%(message)s 用户输出的消息
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(levelno)s 数字形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s  调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有

日志级别

logger,handler和日志消息的调用可以有具体的日志级别(Level),只有在日志消息的级别大于logger和handler的级别。

日志等级(level) 描述
DEBUG 最详细的日志信息,典型应用场景是 问题诊断
INFO 信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作
WARNING 当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的
ERROR 由于一个更严重的问题导致某些功能不能正常运行时记录的信息
CRITICAL 当发生严重错误,导致应用程序不能继续运行时记录的信息

使用

日志简单使用: logging.basicConfig([**kwargs])

Does basic configuration for the logging system by creating a StreamHandler with a defaultFormatter and adding it to the root logger. The functionsdebug(),info(),warning(),error() andcritical() will callbasicConfig() automatically if no handlers are defined for the root logger.
This function does nothing if the root logger already has handlers configured for it.
翻译:
通过使用defaultFormatter创建StreamHandler并将其添加到根记录器,为日志记录系统进行基本配置。如果没有为根记录器定义处理程序,functionsdebug(),info(),warning(),error()和critical()将自动调用basicConfig()。
如果根记录器已经为它配置了处理程序,该函数不会执行任何操作。

import logging

def test1():
    logging.basicConfig(
        format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
        filename='test.log',
        level=logging.DEBUG,
        filemode='w'
    )
    logging.info('hi')
    logging.debug('hello')

test1()

日志文件内容:
2018-04-17 09:20:25,740 - root - INFO - hi
2018-04-17 09:20:25,740 - root - DEBUG - hello

logging模块日志流处理流程

import logging

def test2():
    logger = logging.getLogger("simple_example")
    logger.setLevel(logging.INFO)
    # 设置日志格式
    formatter = logging.Formatter(
        "%(asctime)s - %(name)s - %(levelname)s - %(message)s")

    # 建立一个filehandler来把日志记录在文件里,级别为debug以上
    fh = logging.FileHandler("spam.log", mode='w')
    fh.setLevel(logging.DEBUG)
    fh.setFormatter(formatter)  # 设置格式

    # 建立一个streamhandler来把日志打在CMD窗口上,级别为error以上
    ch = logging.StreamHandler()
    ch.setLevel(logging.ERROR)
    ch.setFormatter(formatter)  # 设置格式

    # 将相应的handler添加在logger对象中
    logger.addHandler(ch)
    logger.addHandler(fh)

    # 开始打日志
    logger.debug("debug message")
    logger.info("info message")
    logger.warn("warn message")
    logger.error("error message")
    logger.critical("critical message")

test2()

控制台输出:
2018-04-17 09:29:27,009 - __main__ - ERROR - error message
2018-04-17 09:29:27,009 - __main__ - CRITICAL - critical message

spam.log:
2018-04-17 09:38:21,802 - simple_example - INFO - info message
2018-04-17 09:38:21,802 - simple_example - WARNING - warn message
2018-04-17 09:38:21,802 - simple_example - ERROR - error message
2018-04-17 09:38:21,802 - simple_example - CRITICAL - critical message

filter使用

import logging

def test4():
    # 创建2个logger
    logger1 = logging.getLogger('mylogger')
    logger1.setLevel(logging.DEBUG)

    logger2 = logging.getLogger('mylogger.child1')
    logger2.setLevel(logging.WARNING)

    # 再创建一个handler,用于输出到控制台
    ch = logging.StreamHandler()

    # 定义handler的输出格式formatter
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    ch.setFormatter(formatter)

    # 定义一个filter
    # TODO

    # 给logger添加handler
    logger1.addHandler(ch)
    logger2.addHandler(ch)

    # 记录一条日志
    logger1.debug('logger1 debug message')
    logger1.info('logger1 info message')
    logger1.warning('logger1 warning message')
    logger1.error('logger1 error message')
    logger1.critical('logger1 critical message')

    logger2.debug('logger2 debug message')
    logger2.info('logger2 info message')
    logger2.warning('logger2 warning message')
    logger2.error('logger2 error message')
    logger2.critical('logger2 critical message')

test4()

输出:
2018-04-17 10:27:52,497 - mylogger - DEBUG - logger1 debug message
2018-04-17 10:27:52,497 - mylogger - INFO - logger1 info message
2018-04-17 10:27:52,497 - mylogger - WARNING - logger1 warning message
2018-04-17 10:27:52,497 - mylogger - ERROR - logger1 error message
2018-04-17 10:27:52,497 - mylogger - CRITICAL - logger1 critical message
2018-04-17 10:27:52,497 - mylogger.child1 - WARNING - logger2 warning message
2018-04-17 10:27:52,497 - mylogger.child1 - WARNING - logger2 warning message
2018-04-17 10:27:52,497 - mylogger.child1 - ERROR - logger2 error message
2018-04-17 10:27:52,497 - mylogger.child1 - ERROR - logger2 error message
2018-04-17 10:27:52,497 - mylogger.child1 - CRITICAL - logger2 critical message
2018-04-17 10:27:52,497 - mylogger.child1 - CRITICAL - logger2 critical message

在 TODO 处加上以下两句
filter = logging.Filter('mylogger.child1')
ch.addFilter(filter)

加上后输出:
2018-04-17 10:30:54,364 - mylogger.child1 - WARNING - logger2 warning message
2018-04-17 10:30:54,364 - mylogger.child1 - WARNING - logger2 warning message
2018-04-17 10:30:54,364 - mylogger.child1 - ERROR - logger2 error message
2018-04-17 10:30:54,364 - mylogger.child1 - ERROR - logger2 error message
2018-04-17 10:30:54,364 - mylogger.child1 - CRITICAL - logger2 critical message
2018-04-17 10:30:54,364 - mylogger.child1 - CRITICAL - logger2 critical message

log 配置

import logging.config

def test3():
    # 日志的加载
    logging.config.fileConfig("conf_log.txt")
    root_logger = logging.getLogger('root')
    root_logger.debug('debug')

test3()

输出:
2018-04-17 09:45:05,565 - root - DEBUG - debug

conf_log.txt 文件

[loggers]
keys=root

[handlers]
keys=consoleHandler

[formatters]
keys=fmt

[logger_root]
level=DEBUG
handlers=consoleHandler

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=fmt
args=(sys.stdout,)

[formatter_fmt]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s

参考文章:
python logging 日志使用
Python之日志处理(logging模块)
每个 Python 程序员都要知道的日志实践
Python中内置的日志模块logging用法详解
Django 如何使用logging打印日志

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

推荐阅读更多精彩内容

  • logging模块介绍: logging是python内置的标准库模块,模块提供不同的日志级别,并可以采用不同的方...
    4ffde5305e8f阅读 2,832评论 0 2
  • 本篇文章主要对 python logging 的介绍加深理解。更主要是 讨论在多进程环境下如何使用logging ...
    doudou0o阅读 41,066评论 52 42
  • 前言 在自动化测试实践过程中,必不可少的就是进行日志管理,方便调试和生产问题追踪,python提供了logg...
    苦叶子阅读 814评论 0 0
  • 在现实生活中,记录日志非常重要。银行转账时会有转账记录;飞机飞行过程中,会有黑盒子(飞行数据记录器)记录飞行过程中...
    chliar阅读 765评论 1 0
  • 桂馨香, 菊绽放, 向晚偶闻虫唱。 风云淡, 玉盘开, 推窗请月来。 秋月璀, 帘儿坠, 一片相思难寐。 蛩声噤,...
    大老鲍阅读 469评论 6 24