快速入门
基础知识
日志的作用是跟踪,django项目中不可缺少。
派出:
控制台输出:print()
报告事件,发生在一个程序的正常运行:logging.info() 或 logging.debug()
发出警告关于一个特定的运行时事件:warnings.warn() 或 logging.warning()
报告一个错误对于一个特定的运行时事件:异常处理
报告一个错误当没有引发一个异常:logging.error()、logging.exception() 或 logging.critical()
级别:
DEBUG:详细的信息,通常只出现在诊断问题上
INFO:确认一切按预期运行
WARNING:一个迹象表明,一些意想不到的事情发生了,或表明一些问题在不久的将来(例如。磁盘空间低”)。这个软件还能按预期工作
ERROR:个更严重的问题,软件没能执行一些功能
CRITICAL:一个严重的错误,这表明程序本身可能无法继续运行
日志一共分成5个等级,从低到高分别是:DEBUG INFO WARNING ERROR CRITICAL。这5个等级,也分别对应5种打日志的方法: debug 、info 、warning 、error 、critical。
默认的是WARNING,当在WARNING或之上时才被跟踪。
有两种方式记录跟踪,一种输出控制台,另一种是记录到文件中,如日志文件。
简单日志操作
写入一个文件里面:
#Logging to a file
import os
import logging
FILE = os.getcwd()
logging.basicConfig(filename=os.path.join(FILE,'log.txt'),level=logging.DEBUG)
logging.debug('写进去')
logging.info('滚进去')
logging.warning('也滚进去')
运行之后,打开该文件,效果如下:
多个模块中操作日志
定义log1.py文件
#log1.py
import logging
def lo():
logging.info('log1--')
定义log2.py文件
#log2.py
import logging
import os
FILE = os.getcwd()
import log1
def main():
logging.basicConfig(filename=os.path.join(FILE,'log.txt'),level=logging.INFO)
logging.info('start--')
log1.lo()
logging.info('end--')
if __name__ == '__main__':
main()
运行后打开log.txt,结果如下:
INFO:root:start--
INFO:root:log1--
INFO:root:end--
日志的格式化字符串
import logging
logging.warning('name:%s msg:%s','BeginMan','Hi') #方式一
logging.warning('name:%s msg:%s' %('BeginMan','Hi')) #方式二
logging.warning('name:{0} msg:{1}'.format('BeginMan','Hi')) #方式三
from string import Template #方式四
msg = Template('name:$who msg:$what')
logging.warning(msg.substitute(who='BeginMan',what='Hi'))
改变显示消息格式
指定自己所需的格式,如下:
import logging
logging.basicConfig(format='%(levelname)s:%(message)s')
logging.warning('msg') #WARNING:msg
logging.basicConfig(format='Hi,试试这个:%(asctime)s:%(message)s')
logging.warning('msg') #Hi,试试这个:2013-09-22 14:25:21,936:msg
logging.basicConfig(format='%(asctime)s:%(message)s',datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('msg') #09/22/2013 02:28:14 PM:msg
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: 打印日志信息
例:
#coding:utf-8
import os
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 = os.path.join('log.txt'),
filemode='w')
logging.info('msg')
logging.debug('msg2') #09/22/2013 02:28:14 PM:msg
打开文件显示如下:
Wed, 20 Jul 2016 20:12:14:hello.py[line:9] INFO msg
Wed, 20 Jul 2016 20:12:14:hello.py[line:10] DEBUG msg2
这种格式字符串参见:http://docs.python.org/2.7/library/logging.html#logrecord-attributes
高级进阶
接下来学习一些日志组件以及一些高级部分。日志组件包括:loggers、handlers、filters、formatters。
Logger 对象扮演了三重角色。首先,它暴露给应用几个方法以便应用可以在运行时写log;其次,Logger对象按照log信息的严重程度或者根据filter对象来决定如何处理log信息(默认的过滤功能);最后,logger还负责把log信息传送给相关的loghandlers。
Handler对象负责分配合适的log信息(基于log信息的严重 程度)到handler指定的目的地。Logger对象可以用addHandler()方法添加零个或多个handler对象到它自身。一个常见的场景是,一个应用可能希望把所有的log信息都发送到一个log文件中去,所有的error级别以上的log信息都发送到stdout,所有critical 的log信息通过email发送。这个场景里要求三个不同handler处理,每个handler负责把特定的log信息发送到特定的地方。
filter:细致化,选择哪些日志输出
format:设置显示格式
logging.basicConfig ( [ * * kwargs ] )
该语句是日志模块配置基本信息。kwargs 支持如下几个关键字参数:
filename :日志文件的保存路径。如果配置了些参数,将自动创建一个FileHandler作为Handler;
filemode :日志文件的打开模式。 默认值为’a’,表示日志消息以追加的形式添加到日志文件中。如果设为’w’, 那么每次程序启动的时候都会创建一个新的日志文件;
format :设置日志输出格式;
datefmt :定义日期格式;
level :设置日志的级别.对低于该级别的日志消息将被忽略;
stream :设置特定的流用于初始化StreamHandler。
演示如下:
import logging
import os
FILE=os.getcwd()
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 = os.path.join(FILE,'log.txt'),
filemode='w')
logging.info('msg')
logging.debug('msg2')
输出结果如下:
Wed, 20 Jul 2016 20:25:50:hello.py[line:11] INFO msg
Wed, 20 Jul 2016 20:25:50:hello.py[line:12] DEBUG msg2
logging.getLogger ( [ name ] )
创建Logger对象。日志记录的工作主要由Logger对象来完成。
在调用getLogger时要提供Logger的名称(注:多次使用相同名称 来调用getLogger,返回的是同一个对象的引用。),Logger实例之间有层次关系,这些关系通过Logger名称来体现,如:
>>>p = logging.getLogger("root")
>>>
>>>c1 = logging.getLogger("root.c1")
>>>
>>>c2 = logging.getLogger("root.c2")
>>>
例子中,p是父logger, c1,c2分别是p的子logger。c1, c2将继承p的设置。如果省略了name参数, getLogger将返回日志对象层次关系中的根Logger。
import logging
'''命名'''
log2=logging.getLogger('BeginMan') #生成一个日志对象
print(log2) #<logging.Logger object at 0x00000000026D1710>
'''无名'''
log3 = logging.getLogger()
print(log3) #<logging.RootLogger object at 0x0000000002721630> 如果没有指定name,则返回RootLogger
'''最好的方式'''
log = logging.getLogger(__name__)#__name__ is the module’s name in the Python package namespace.
print log #<logging.Logger object at 0x0000000001CD5518> Logger对象
print( __name__) #__main__
Logger对象
通过logging.getLogger(nam)来获取Logger对象
Class logging.Logger
有如下属性和方法:
- Logger.propagate
例:print (log.propagate)
具体参考:http://docs.python.org/2.7/library/logging.html Logger.setLevel(lvl) ——————– 设置日志的级别。对于低于该级别的日志消息将被忽略。
import logging
import os
logging.basicConfig(format="%(levelname)s,%(message)s",filename=os.path.join(os.getcwd(),'log.txt'),level=logging.DEBUG)
log = logging.getLogger('root.set') #Logger对象
print(log.propagate) #1
log.setLevel(logging.WARN) #日志记录级别为WARNNING
log.info('msg') #不会被记录
log.debug('msg') #不会被记录
log.warning('msg')
log.error('msg')
Logger.debug ( msg [ ,* args [ , * * kwargs ] ] )
记录DEBUG级别的日志信息。参数msg是信息的格式,args与kwargs分别是格式参数。
例:
import logging
import os
logging.basicConfig(filename = os.path.join(os.getcwd(), 'log.txt'), level = logging.DEBUG)
log = logging.getLogger('root')
log.debug('%s, %s, %s', *('error', 'debug', 'info'))
log.debug('%(module)s, %(info)s', {'module': 'log', 'info': 'error'})
输出结果如下:
DEBUG:root:error, debug, info
DEBUG:root:log, error
同上
Logger.info ( msg [ , *args[ , **kwargs ] ] )
Logger.warnning ( msg [ , *args[ , **kwargs ] ] )
Logger.error ( msg [ , *args[ , **kwargs ] ] )
Logger.critical ( msg [ , *args[ , **kwargs] ] )
Logger.log ( lvl, msg [ , * args [ , * * kwargs ] ] )
记录日志,参数lvl用户设置日志信息的级别。参数msg, *args, **kwargs的含义与Logger.debug一样。
log.log ( logging.ERROR, ‘%(module)s %(info)s’, {‘module’:’log日志’,’info’:’error’}) #ERROR,log日志 error
log.log(logging.ERROR,’再来一遍:%s,%s’,*(‘log日志’,’error’)) #ERROR,再来一遍:log日志,error
Logger.exception ( msg [ , *args ] )
以ERROR级别记录日志消息,异常跟踪信息将被自动添加到日志消息里。Logger.exception通过用在异常处理块中,如:
例:
import logging
import os
logging.basicConfig(format="%(levelname)s,%(message)s",filename=os.path.join(os.getcwd(),'log.txt'),level=logging.DEBUG)
log = logging.getLogger('root') #Logger对象
try:
raise Exception,u'错误异常'
except:
log.exception('exception') #异常信息被自动添加到日志消息中
输出结果如下:
ERROR,exception
Traceback (most recent call last):
File "E:/workspace/hello.py", line 7, in
raise Exception,u'错误异常'
Exception: \u9519\u8bef\u5f02\u5e38
Logger.addFilter(filt)
作用:指定过滤器
Logger.removeFilter(filt)
作用:移除指定的过滤器
Logger.filter(record)
….其他的后面介绍
Handler对象、Formatter对象、Filter对象、Filter对象
这里简要介绍
#coding=utf8
'''
Created on 2013年9月23日
Function : Handler对象、Formatter对象、Filter对象、Filter对象
@author : BeginMan
'''
import logging
import os
'''Logger'''
l = logging.Logger('root') #创建Logger对象
log = logging.getLogger('root') #通过logging.getLogger创建Logger对象
print (l) #<logging.Logger object at 0x0000000001DF5B70>
print (log) #<logging.Logger object at 0x00000000022A16D8>
'''Handler'''
handler = logging.Handler() #创建Handler对象
handler.__init__(logging.DEBUG) #通过设置level来初始化Handler实例
handler.createLock() #初始化一个线程锁可以用来序列化访问底层I / O功能,这可能不是线程安全的。
handler.acquire() #获取线程锁通过handler.createLock()
handler.release() #释放线程锁通过获取handler.acquire()
handler.setLevel(logging.DEBUG) #设置临界值,如果Logging信息级别小于它则被忽视,当一个handler对象被创建,级别没有被设置,导致所有的信息会被处理。
handler.setFormatter("%(levelname)s,%(message)s") #设置格式
# handler.addFilter(filter) #添加指定的过滤器
# handler.removeFilter(filter) #移除指定的过滤器
# handler.filter(record) #通过设置过滤器适用于记录并返回真值如果要处理的记录
handler.flush() #确保所有的日志输出已经被刷新
handler.close() #收拾任何所使用资源处理程序,
# handler.handle(record) #有条件地发出指定的日志记录,这取决于过滤器可能被添加到处理程序。
# handler.handlerError(record) #处理错误
# handler.format(record) #格式输出
# handler.emit(record)
#Formatter:http://docs.python.org/2.7/library/logging.html#logging.Formatter
'''Formatter:
the base Formatter allows a formatter string to be specified,is none ,used default value '%(message)s'
class logging.Formatter(fmt=None,datefmt=None)
If no fmt is specified, '%(message)s' is used. If no datefmt is specified, the ISO8601 date format is used.
'''
fm = logging.Formatter('%(levelname)s:%(message)s','%m/%d/%Y %I:%M:%S %p')
print fm #<logging.Formatter object at 0x0000000002311828>
#有如下方法:format()、formatTime()、formatException()
#http://docs.python.org/2.7/library/logging.html#formatter-objects
'''Filter'''
'''
class logging.Filter(name=''):
返回Filter实例,If name is specified, it names a logger which, together with its children,
will have its events allowed through the filter. If name is the empty string, allows every event.
用于Loggers、Handlers等过滤的设置
如果一个过滤器初始化为'A.B',则允许'A.B/A.B.C/A.B.C.D/A.B.D'等,但不允许'A.BB/B.A'等通过
如果初始化为空字符串,则没有过滤。
它有filter()方法
'''
'''LogRecord '''
'''class logging.LogRecord(name, level, pathname, lineno, msg, args, exc_info, func=None)
LogRecord 实例可以被Logger自动创建.也可以通过makeLogRecord()来创建'''
#http://docs.python.org/2.7/library/logging.html#logrecord-objects