文档章节

python logging - vasks

vasks
 vasks
发布于 2015/04/02 19:28
字数 2281
阅读 114
收藏 4

make sure your python version > Python 2.3 所有的logging对象都是从root logging对象“继承”而来?!
###1 从一个小案例说起: cat howto_logging.py

#coding=utf8
# file name:	howto_logging.py
# this file shows how to use logging
# made by vasks, email:vasks@qq.com
import logging

# 创建一个logger,级别:DEBUG
logger = logging.getLogger('Err_Logger')
logger.setLevel(logging.DEBUG)

# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('err.log')
fh.setLevel(logging.DEBUG)

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

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

# 给logger添加handler
logger.addHandler(fh)
logger.addHandler(ch)

# 记录日志 NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL
logger.debug('just a debug')
logger.info('just a info')
logger.warning('waring,please check out')
logger.error('error,oh no')
logger.critical("critical,it doesn't work")  

终端输出执行结果:

2015-04-02 17:03:29,421 - Err_Logger - DEBUG - just a debug - 29
2015-04-02 17:03:29,423 - Err_Logger - INFO - just a info - 30
2015-04-02 17:03:29,423 - Err_Logger - WARNING - waring,please check out - 31
2015-04-02 17:03:29,423 - Err_Logger - ERROR - error,oh no - 32
2015-04-02 17:03:29,423 - Err_Logger - CRITICAL - critical,it doesn't work - 33
[Finished in 0.1s]

err.log的结果:

cat err.log
2015-04-02 17:03:29,421 - Err_Logger - DEBUG - just a debug - 29
2015-04-02 17:03:29,423 - Err_Logger - INFO - just a info - 30
2015-04-02 17:03:29,423 - Err_Logger - WARNING - waring,please check out - 31
2015-04-02 17:03:29,423 - Err_Logger - ERROR - error,oh no - 32
2015-04-02 17:03:29,423 - Err_Logger - CRITICAL - critical,it doesn't work - 33

2. logging 详解

####2.1 logger:提供日志接口,供应用代码使用。logger最长用的操作有两类:配置和发送日志消息。

  • logging.getLogger(name): 可以通过logging.getLogger(name)获取logger对象,如果不指定name则返回root对象,多次使用相同的name调用getLogger方法返回同一个logger对象。
  • Logger.setLevel(lvl): 设置logger的level, level有以下几个级别:NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL 如果把looger的级别设置为INFO, 那么小于INFO级别的日志都不输出, 大于等于INFO级别的日志都输出。小于的就不会输出。

####2.2 handler:将日志记录发送到合适的目的地,比如文件,socket等。一个logger对象可以通过addHandler方法添加0到多个handler,每个handler又可以定义不同日志级别,以实现日志分级过滤显示。 我们这里设置了两个,一个输出到终端,一个输出到err.log文件。 handler主要有以下几种: StreamHandler: 输出到控制台 FileHandler: 输出到文件 handler还可以设置自己的level以及输出格式。

####2.3 filter:提供一种优雅的方式决定一个日志记录是否发送到handler。

####2.4 formatter:指定日志记录输出的具体格式。formatter的构造方法需要两个参数:消息的格式字符串和日期字符串,这两个参数都是可选的。

更多的格式:

格式                       描述(代表什么)
%(name)s	        Name of the logger (logging channel).
%(levelno)s	        Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
%(levelname)s	Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
%(pathname)s	Full pathname of the source file where the logging call was issued (if available).
%(filename)s	        Filename portion of pathname.
%(module)s	        Module (name portion of filename).
%(funcName)s	Name of function containing the logging call.
%(lineno)d	        Source line number where the logging call was issued (if available).
%(created)f	        Time when the LogRecord was created (as returned by time.time()).
%(relativeCreated)d	Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
%(asctime)s	        Human-readable time when the LogRecord was created. By default this is of the form “2003-07-08 16:49:45,896”     (the numbers after the comma are millisecond portion of the time).
%(msecs)d	        Millisecond portion of the time when the LogRecord was created.
%(thread)d	        Thread ID (if available).
%(threadName)s	Thread name (if available).
%(process)d	        Process ID (if available).
%(message)s	        The logged message, computed as msg % args.

这里是中文的:

%(name)s        Logger的名字
%(levelno)s     数字形式的日志级别
%(levelname)s     文本形式的日志级别
%(pathname)s        调用日志输出函数的模块的完整路径名,可能没有
%(filename)s            调用日志输出函数的模块的文件名
%(module)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        用户输出的消息

####2.5 logging.basicConfig() ####2.5.1 logging.basicConfig([**kwargs])

  • 这个函数用来配置root logger, 为root logger创建一个Handler, 设置默认的格式。

  • 这些函数: logging.debug()、logging.info()、logging.warning()、 logging.error()、logging.critical() 如果调用的时候发现root logger没有任何 handler, 会自动调用basicConfig添加一个handler

  • 如果root logger已有handler, 这个函数不做任何事情,使用basicConfig来配置root logger的输出格式和level。 例子:

          import logging
          logging.basicConfig(format='%(levelname)s:%(message)s', 
                                                  level=logging.DEBUG)
          logging.debug('This message should appear on the console')
    

关于root logger以及logger的父子关系

前面多次提到root logger, 实际上logger实例之间还有父子关系, root logger就是处于 最顶层的logger, 它是所有logger的祖先。如下图: root logger

root logger是默认的logger 如果不创建logger实例, 直接调用logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()这些函数,那么使用的logger就是 root logger, 它可以自动创建,也是单实例的。

如何得到root logger 通过logging.getLogger()或者logging.getLogger("")得到root logger实例。

默认的level root logger默认的level是logging.WARNING

如何表示父子关系 logger的name的命名方式可以表示logger之间的父子关系. 比如:

    parent_logger = logging.getLogger('foo')
    child_logger = logging.getLogger('foo.bar')

什么是effective level logger有一个概念,叫effective level。 如果一个logger没有显示地设置level,那么它就 用父亲的level。如果父亲也没有显示地设置level, 就用父亲的父亲的level,以此推.... 最后到达root logger,一定设置过level。默认为logging.WARNING child loggers得到消息后,既把消息分发给它的handler处理,也会传递给所有祖先logger处理,

来看一个例子

import logging

# 设置root logger
r = logging.getLogger()
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
r.addHandler(ch)

# 创建一个logger作为父亲
p = logging.getLogger('foo')
p.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(message)s')
ch.setFormatter(formatter)
p.addHandler(ch)

# 创建一个孩子logger
c = logging.getLogger('foo.bar')
c.debug('foo')  

输出如下:

2015-04-02 18:44:38,128 - foo
2015-04-02 18:44:38,128 - DEBUG - foo
[Finished in 0.2s]

可见, 孩子logger没有任何handler,所以对消息不做处理。但是它把消息转发给了它的父亲以及root logger。最后输出两条日志。

再看个例子:

    import logging
     
    # set up logging to file - see previous section for more details
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                        datefmt='%m-%d %H:%M',
                        filename='mylogging.log',
                        filemode='w')
    # define a Handler which writes INFO messages or higher to the sys.stderr
    console = logging.StreamHandler()
    console.setLevel(logging.WARNING)
    # set a format which is simpler for console use
    formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
    # tell the handler to use this format
    console.setFormatter(formatter)
    # add the handler to the root logger
    logging.getLogger('').addHandler(console)
     
    # Now, we can log to the root logger, or any other logger. First the root...
    logging.info('Jackdaws love my big sphinx of quartz.')
     
    # Now, define a couple of other loggers which might represent areas in your
    # application:
     
    logger1 = logging.getLogger('myapp.area1')
    logger2 = logging.getLogger('myapp.area2')
     
    logger1.debug('Quick zephyrs blow, vexing daft Jim.')
    logger1.info('How quickly daft jumping zebras vex.')
    logger2.warning('Jail zesty vixen who grabbed pay from quack.')
    logger2.error('The five boxing wizards jump quickly.')

终端输出:

    myapp.area2 : WARNING  Jail zesty vixen who grabbed pay from quack.
    myapp.area2 : ERROR    The five boxing wizards jump quickly.
    [Finished in 0.1s]

终端下 StreamHandler(): logging.info root自己info没有设置的级别warning大,不输出 logger1 的info和debug没有设置的级别:warning 大,所以不输出 logger2符合条件,输出 文本输出:

04-02 19:15 root                 INFO     Jackdaws love my big sphinx of quartz.
04-02 19:15 myapp.area1  DEBUG    Quick zephyrs blow, vexing daft Jim.
04-02 19:15 myapp.area1  INFO     How quickly daft jumping zebras vex.
04-02 19:15 myapp.area2  WARNING  Jail zesty vixen who grabbed pay from quack.
04-02 19:15 myapp.area2  ERROR    The five boxing wizards jump quickly.

basicConfig中设置的报警级别是debug,所以大家都输出了,输出到了文本。

####2.5.1 详细说下basicConfig参数:

    filename: 指定日志文件名
    filemode: 和file函数意义相同,指定日志文件的打开模式,'w'或'a'
    format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:
     %(levelno)s: 打印日志级别的数值
     %(levelname)s: 打印日志级别名称
     %(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
     %(filename)s: 打印当前执行程序名
     %(funcName)s: 打印日志的当前函数
     %(lineno)d: 打印日志的当前行号
     %(asctime)s: 打印日志的时间
     %(thread)d: 打印线程ID
     %(threadName)s: 打印线程名称
     %(process)d: 打印进程ID
     %(message)s: 打印日志信息
    datefmt: 指定时间格式,同time.strftime()
    level: 设置日志级别,默认为logging.WARNING
    stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略

本文引用这些博客:

© 著作权归作者所有

共有 人打赏支持
vasks
粉丝 21
博文 40
码字总数 34341
作品 0
朝阳
程序员
私信 提问
python模块介绍- logging 日志工具

python模块介绍- logging 日志工具 目录 项目简介... 1 简介:... 2 应用程序和库中使用Logging. 3 记录日志到文件... 4 日志文件轮转... 4 日志级别... 5 日志实例命名... 6 项目简介 Pyth...

长平狐
2013/12/25
285
0
使用Logging Handler自动上传Python程序日志到日志服务

想要日志上云,又不想修改程序代码? 或者不希望进行相对复杂的客户端部署?那么您需要使用Logging Handler,现在Python程序也支持了! 概述 使用Python SDK提供的Log Handler可以实现每一条P...

成喆
2018/04/13
0
0
Python第三章模块-张明阳-专题视频课程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a2011480169/article/details/83580545 Python第三章模块—142人已学习 课程介绍 介绍Python在项目当中常用的...

安静的技术控
2018/04/20
0
0
Python日志(logging)模块使用方法简介

介绍 A logger is configured to have a log level. This log level describes the severity of the messages that the logger will handle. Python defines the following log levels: Each......

AltBoy
2018/06/26
0
0
使用Python Log Handler自动上传并解析JSON格式的日志

概述 使用Python SDK提供的Log Handler可以实现每一条Python程序的日志在不落盘的情况下自动上传到日志服务上。与写到文件再通过各种方式上传比起来,有如下优势: 实时性:主动直接发送,不...

成喆
2018/05/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

树形结构的数据库表Schema设计

程序设计过程中,我们常常用树形结构来表征某些数据的关联关系,如企业上下级部门、栏目结构、商品分类等等,通常而言,这些树状结构需要借助于数据库完成持久化。然而目前的各种基于关系的数...

太菜鸟
34分钟前
0
0
Pod在多可用区worker节点上的高可用部署

一、 需求分析 当前kubernetes集群中的worker节点可以支持添加多可用区中的ECS,这种部署方式的目的是可以让一个应用的多个pod(至少两个)能够分布在不同的可用区,起码不能分布在同一个可用...

迷你芊宝宝
43分钟前
0
0
使用maven命令上传jar包到仓库

mvn deploy:deploy-file -DgroupId=com.jz.tss.service -DartifactId=tss-service -Dversion=1.9.02-SNAPSHOT -Dfile=E:/Workspace/tss-service/build/oracle/TSS-Service/WEB-INF/lib/TSS-S......

GodIsCj
44分钟前
2
0
mysql 向下无限递归(不使用函数,单纯sql)

表结构和数据 CREATE TABLE table1(id int, name varchar(10), parent_id int); INSERT table1 VALUES (1, 'Home', 0), (2, 'About', 1), (3, 'Contact', 1), (4, 'Legal', 2), ......

一雨成东
44分钟前
0
0
面试官问:ZooKeeper 一致性协议 ZAB 原理

一致性协议有很多种,比如 Paxos,Raft,2PC,3PC等等,今天我们讲一种协议,ZAB 协议,该协议应该是所有一致性协议中生产环境中应用最多的了。为什么呢?因为他是为 Zookeeper 设计的分布式...

Java爬坑之路
47分钟前
27
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部