logging 模块的简单使用:

配置输出日志到文件


导入模块
import logging,os
FILE = os.getcwd()
设置文件路径,默认是追加到文件中,不过可以设置filemode="w",为重写进去。
logging.basicConfig(filename=os.path.join(FILE,"dosubprocess.log"),filemode="w",
                    format="%(levelname)s:%(message)s",level=logging.INFO)
                    
                    
                    

可以在外面设置级别


import logging
logging.basicConfig(level="laowang")
#必须调用getLOgger获得一个loggging对象后,才可以为他设置级别。
log=logging.getLogger(__name__)
#logging的属性,propagate,意思是是否消息是否层层上传。
print(log.propagate)
#设置logging对象的级别
log.setLevel(logging.WARN)

logging创建流handler,将信息显示到控制台,

import logging,os
logging.basicConfig(filename=os.path.join(os.getcwd(),"my_property.log"),
                    format="%(levelname)-10s %(asctime)-20s %(message)s",
                    datefmt="%m/%d/%Y %I:%M:%S",
                    level=logging.DEBUG,
                    filemode="w")

console=logging.StreamHandler()
console.setLevel(logging.INFO)
formatter=logging.Formatter("%(levelname)-10s %(asctime)-20s %(message)s")
console.setFormatter(formatter)
logging.getLogger("").addHandler(console)

'''
快速入门
基础知识
日志的作用是跟踪,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或之上时才被跟踪。
有两种方式记录跟踪,一种输出控制台,另一种是记录到文件中,如日志文件。

日志一共分成5个等级,从低到高分别是:DEBUG INFO WARNING ERROR CRITICAL。这5个等级,也分别对应5种打日志的方法: debug 、info 、warning 、error 、critical。
默认的是WARNING,当在WARNING或之上时才被跟踪。
有两种方式记录跟踪,一种输出控制台,另一种是记录到文件中,如日志文件

'''

'''
简单日志操作
写入一个文件里面:
'''
#logging to file
# import os
# import logging
#
# # with open("log.txt","w",encoding="utf-8") as f:
# #     f.write("")
#
# FILE =os.getcwd()
# logging.basicConfig(filename=os.path.join(FILE,"log.txt"),level=logging.DEBUG)
# logging.debug("写进去")
# logging.info("滚进去")
# logging.warning("也滚进去")
'''
来学习一些日志组件以及一些高级部分。
日志组件包括: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:设置显示格式

'''
'''
ogging.basicConfig ( [ * * kwargs ] )
该语句是日志模块配置基本信息。kwargs 支持如下几个关键字参数:

filename :日志文件的保存路径。如果配置了些参数,将自动创建一个FileHandler作为Handler;

filemode :日志文件的打开模式。 默认值为’a’,表示日志消息以追加的形式添加到日志文件中。如果设为’w’, 那么每次程序启动的时候都会创建一个新的日志文件;

format :设置日志输出格式;

datefmt :定义日期格式;

level :设置日志的级别.对低于该级别的日志消息将被忽略;

stream :设置特定的流用于初始化StreamHandler。

'''
'''
logging.getLogger ( [ name ] )
创建Logger对象。日志记录的工作主要由Logger对象来完成。

在调用getLogger时要提供Logger的名称(注:多次使用相同名称 来调用getLogger,
返回的是同一个对象的引用。),Logger实例之间有层次关系,这些关系通过Logger名称来体现,如
'''
# import logging

'''命名'''
# log2=logging.getLogger("BeginMan") #生成一个日志对象
# print(log2)#<logging.Logger object at 0x00000000026D1710>
'''无名'''
# log3=logging.getLogger()
# print(log3)

'''最好的方式'''
# log = logging.getLogger(__name__)#_name__ is the module’s name in the Python package namespace.
# print(log)
# print(__name__)
'''
Logger对象,
有如下属性和方法:
Logger.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)
#
# log.setLevel(logging.WARN) #日志记录级别为WARNNING
# log.info("msg")
# log.debug("msg")
# log.warning("msg")
# log.error("msg")
#
'''
Handler对象、Formatter对象、Filter对象、Filter对象

'''

# import logging
# import os
# '''logger'''
# l=logging.Logger("root")  #创建logger对象
# log=logging.getLogger("root")  #通过logging.getlogger创建对象
#
# print(l)
# print(log)
#
# '''Handler'''
# handler=logging.Handler() #创建Handler对象
# handler.__init__(logging.DEBUG)  #通过设置levell劳初始刷handler实例
# handler.createLock()#初始化一个县城索,可以用来序列化,访问底层i/ogongneng,这可鞥不是县城安全的
# handler.acquire() #获取线程锁,通过handler.createLock()
# handler.release() #释放获得的县城索
# handler.setLevel(logging.DEBUG) #设置临界值,如果logging信息级别小于他的责被忽视
# handler.setFormatter("%(levelname)s,%(message)s") #设置格式
# handler.addFilter(filter)#
'''
3.将日志同时输出到文件和屏幕
'''
# 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="myapp.log",
#                     filemode="w")
# 定义一个StreamHandler,将INFO级别或更高的日志信息打印到标准错误,
# 并将其添加到当前的日志处理对象
# console=logging.StreamHandler()
# console.setLevel(logging.INFO)
# formatter=logging.Formatter("%(name)-12s:%(levelname)-8s %(message)s")
# console.setFormatter(formatter)
# logging.getLogger("").addHandler(console)
#
# logging.debug("This is debug message")
# logging.info("This is info message ")
# logging.warning("Thsi is warning message")


# level: 设置日志级别,默认为logging.WARNING
# stream: 指定将日志的输出流,
# 可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,
# 当stream和filename同时指定时,stream被忽略

'''
. 每一个Logger实例的level如同入口,让水流进来,如果这个门槛太高,信息就进不来。例如log2.info('log3 info'),如果log2定义的级别高于info级别,就不会又信息通过log2

2. 如果level没有设置,就用父logger的,如果父logger的level也没有设置,继续找父的父的,最终找到root上,如果root设置了就用它的,如果root没有设置,root的默认值是WARNING

3.消息传递流程:

在某个logger上产生某种级别的信息,首先和logger的level检查,如果消息level低于logger的EffectiveLevl有效级别,消息丢弃,不会再向父logger传递该消息。如果通过(大于等于)检查后,则把消息交给logger所有的handler处理,每一个handler需要和自己level比较来决定是否处理。

 

如果没有一个handler,或者消息已经被handler处理过了,则需要通过本logger的propagate属性是否为True,Ture则把这个消息会继续发给父Logger,当前Logger的父Logger称为当前Logger,新的Logger的所有Handler继续处理消息。

4. logger实例初始的propagate属性为True,即允许想父logger传递消息

5. logger.basicConfig

如果root没有handler,就默认创建一个StreamHandler,如果设置了filename,就创建一个FileHandler。如果设置了format参数,就会用它生成一个formatter对象,并把这个formatter加入到刚才创建的handler上,然后把这些handler加入到root.handlers列表上。level 是设置给root.logger的。

如果root.handlers列表不为空,logging.basicConfig的调用什么都不做。



标准库里面的logging模块,在前面学习线程安全时曾用来解决print被打断的问题,这里会介绍logging模块的功能。

logging模块是线程安全的,不需要客户做任何特殊的工作。它通过使用线程锁实现了这一点; 有一个锁来序列化访问模块的共享数据,
每个处理程序还创建一个锁来序列化访问其底层 I/O。


使用工厂方法返回一个Logger实例。

logging.getLogger([name=None])

 指定name,返回一个名称为name的Logger实例。如果再次使用相同的名字,是实例化一个对象。未指定name,返回Logger实例,名称是root,即根Logger。

Logger是层次结构的,使用 '.' 点号分割,如'a'、'a.b'或'a.b.c.d','a'是'a.b'的父parent,a.b是a的子child。对于foo来说,名字为foo.bar、foo.bar.baz、foo.bam都是foo的后代。

'''

# import logging
# DATEFMT="[%Y-%m-%d %H:%M:%s]"
# FORMAT="%(asctime)s %(thread)d %(message)s"
# logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt=DATEFMT,filename="log.txt")
#
# root=logging.getLogger()
# print(root.name,type(root),root.parent,id(root))
#
# logger=logging.getLogger(__name__)
# print(logger.name,type(logger),id(logger),id(logger.parent))
#
# logger1=logging.getLogger(__name__+".ok")
# print(logger1.name,type(logger1),id(logger1),id((logger1.parent)))
#
# print(logger1.parent,id(logger.parent))
'''
子child的级别设置,不影响父parent的级别:
'''
# import logging
#
# FORMAT="%(asctime)s %(thread)d %(message)s"
# logging.basicConfig(level=logging.WARNING,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")
#
# root=logging.getLogger()
# print(1,root,id(root))
# root.info("my root")
#
# loga=logging.getLogger(__name__)
# print(2,id(loga),id(loga.parent))
# print(3,loga.getEffectiveLevel())
#
# loga.warning("before")
# loga.setLevel(28)
# print(4,loga.getEffectiveLevel)
# loga.info("after")
# loga.warning("after")
'''
Handler

  StreamHandler #不指定使用sys.strerr

    FileHandler #文件

    _StderrHandler #标准输出

  NullHandler #什么都不做

logger实例,如果设置了level,就用它和信息的级别比较,否则,继承最近的祖先的level。

'''

# import logging
# FORMAT ="%(asctime)s %(thread)d %(message)s"
# logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")
#
# root=logging.getLogger()
# print("root",root.getEffectiveLevel())
#
# log1=logging.getLogger("s")
# log1.setLevel(logging.ERROR)
# print("log1:",log1.getEffectiveLevel())
# log1.error("log1 error")
#
# log2=logging.getLogger("s.s1")
# log2.setLevel(logging.WARNING)
# print("log2",log2.getEffectiveLevel())
# log2.warning("log2 warning")
#
#

'''
Handler:

Handler控制日志信息的输出目的地,可以是控制台、文件。

可以单独设置level

可以单独设置格式

可以设置过滤器

 

Handler

  StreamHandler #不指定使用sys.strerr

    FileHandler #文件

    _StderrHandler #标准输出

  NullHandler #什么都不做

'''
# import logging
#
# FORMAT ="%(asctime)s %(thread)d %(message)s"
# logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")
#
# root=logging.getLogger()
# print("root:",root.getEffectiveLevel())
#
# log1=logging.getLogger("s")
# log1.setLevel(logging.ERROR)
# print("log1:",log1.getEffectiveLevel())
# log1.error("log1.error")
#
# log2=logging.getLogger("s.s1")
# log2.setLevel(logging.WARNING)
# print("log2:",log2.getEffectiveLevel())
# log2.warning("log2.warning")

'''
loggerLevel --> FilterConditions --> HandlerLevel --> 
父LoggerFilter --> 父LoggerHandler --> RootHandler --> 标准输出或记录到日志:


'''

import logging,datetime

FORMAT="%(asctime)s %(thread)s %(message)s"
logging.basicConfig(level=logging.WARNING,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")

"--------------root----------------------"
root=logging.getLogger()
print(1,root.getEffectiveLevel())
"---------------------log1---------------------"
log1=logging.getLogger("s")
log1.setLevel(logging.ERROR)
print(2,log1.getEffectiveLevel())

h1=logging.FileHandler("h1.log")
h1.setLevel(logging.INFO)
log1.addHandler(h1)

"----------------log2-----------"
log2=logging.getLogger("s.s2")
log2.setLevel(logging.WARNING)
print(3,log2.getEffectiveLevel())

h2=logging.FileHandler("h2.log")
h2.setLevel(logging.WARNING)
f2=logging.Filter("s.s3")
h2.addFilter(f2)
log2.addHandler(h2)

log2.warning("4,log2 warning---{}".format(datetime.datetime.now()))
如果要实现多个模块用一个定义好的logging模式,可以定义一个模板,
然后各个模块在导入的时候,调用一下,就好啦。
文件一  log1
import logging
from string import Template

def lo():
    logging.info("log1--------------")
    logging.warning("name:%s msg:%s","BeginMan","Hi")
    logging.warning("name:%s msg:%s"%("BeginMan","Hi"))
    logging.warning("name:{0} mag:{1}".format("b而过inMan","HI"))
    msg=Template("name:$who msg:$what")
    logging.warning(msg.substitute(who="BeginMan",what="Hi"))
    
文件log2    
import logging
import os
FIFE  =os.getcwd()
import log1


def main():
    logging.basicConfig(filename=os.path.join(FIFE,"log1.txt"),level=logging.INFO)
    logging.info("start-------------")
    log1.lo()
    logging.info("end---------")
if __name__=="__main__":
    main()

猜你喜欢

转载自blog.csdn.net/weixin_42040854/article/details/81006064
今日推荐