配置输出日志到文件
导入模块 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)
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)#'''无名''' # 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()