标签:
make sure your python version > Python 2.3
cat howto_logging.py
#coding=utf8
# file name: howto_logging
# 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
我们这里设置了两个,一个输出到终端,一个输出到err.log文件。
handler主要有以下几种:
StreamHandler: 输出到控制台
FileHandler: 输出到文件
handler还可以设置自己的level以及输出格式。
更多的格式:
格式 描述(代表什么)
%(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 用户输出的消息
这个函数用来配置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是默认的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,所以大家都输出了,输出到了文本。
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被忽略
本文引用这些博客:
标签:
原文地址:http://my.oschina.net/VASKS/blog/395355