雪人骑士出装

admin · 2017-10-01

  

  正在上一篇著作1万字详解 python logging日记模块 中,长远浅出的诠释了日记的基础道理与用法。但另有少许实质并无触及到,是以这篇著作动作上一篇著作的增加。

  生气这两篇著作能助助你十足清楚日记模块的行使,正在名目中对日记的行使逛刃众余。上一篇还没看的倡导先浏览上一篇

   1、为甚么子记载器没必要要修设日记等第也能够输出?

  假如未正在记载器上显式修设级别,则行使其父记载器的级别动作其无效级别。假如父记载器也没有修设级别,则依此类推,探索父级的父级,直到找到鲜明修设了级其余记载器。根记载器默许下为 WARNING 级别

  

importloggingparent=logging.getLogger("parent")parent.setLevel(logging.INFO)parent.addHandler(logging.StreamHandler())child=logging.getLogger("parent.child")child.info("msg")

 

  输出

  

msg

 

  这里我没有给child修设日记等第,他会从父记载器查找日记级别,是以child也能够输出info级其余日记。对于记载器的经受瓜葛能够参考第一篇著作

   2、为甚么偶然候日记会输出两次?

  看上面例子:

  

importlogging#初始化日记,并修设日记级别(为root修设为DEBUG级别,联络合系StreamHandler,修设BASIC_FORMAT形式)logging.basicConfig(level=logging.DEBUG)#界说root记载器root=logging.getLogger()#界说child记载器child=logging.getLogger("child")console_handler=logging.StreamHandler()#给child绑定治理器child.addHandler(console_handler)#记载一条info日记child.info("childinfo")

 

  输出

  

childinfoINFO:child:childinfo

 

  代码中明显只记载了一越日记,却输出了两次,并且两次的日记形式不相似。这是由于 child 这个记载器增添了一个叫console_handler的治理器, 而root根记载器默许也带有本身的治理器(也是StreamHandler实例)

  

print(root.handlers)#[<StreamHandler<stderr>(NOTSET)>]

 

  依照python中日记模块的治理机制,子记载器记载的音尘会主动鼓吹给父级记载器的联络合系的治理器。是以正在这个例子中,child记载的音尘除了会发给本身的handler外,依然鼓吹给root记载器的handler,所以终极输出了两次,流程图如下

  

  

logging-flow.png

  假如不生气子记载器记载的音尘鼓吹给父级记载器,能够修设记载器的属性propagate为False,封闭鼓吹。

  

child.propagate=False

 

  如许一来,终极输出到终真个日记就惟有child本身的治理器输出的记载

  

childinfo

 

  设置治理器的最佳践诺是给顶级记载器设置治理器,再依照必要创修子记载器, 由于记载终极城市鼓吹给父记载器

  

importloggingparent=logging.getLogger("parent")parent.setLevel(logging.DEBUG)parent.addHandler(logging.StreamHandler())#没必要要给子记载器零丁设置handlerchild=logging.getLogger("parent.child")child.info("msg")

 

  对付日记的流程治理,python官方文档画了一张更为过细的流程图,能够参考

  

  

logging_flow.png

  第一次看推测有点晕,但先看我画的这张图再来看这张图,你就能懂了,为了简化我省去了过滤器以及不停轮回查找父级记载器的这个流程。

   三、 为甚么我的pycharm中输出的日记是赤色?

  不领略你的pycharm输出的日记不论是info新闻依然error新闻,横竖都是赤色,一看认为整屏都是失误。

  

  把上面代码放正在Pycharm运转算作绩:

  

importlogginglogging.basicConfig(level=logging.DEBUG)logging.info("hello")

 

  这是由于行使root记载器记载日记时,默许设置的handler是一个StreamHandler。

  咱们翻开StreamHandler的源码

  

classStreamHandler(Handler):"""Ahandlerclasswhichwritesloggingrecords,appropriatelyformatted,toastream.Notethatthisclassdoesnotclosethestream,assys.stdoutorsys.stderrmaybeused."""terminator=
def__init__(self,stream=None):"""Initializethehandler.Ifstreamisnotspecified,sys.stderrisused."""Handler.__init__(self)ifstreamisNone:stream=sys.stderrself.stream=stream

 

  初始化这个Handler时,会收受一个stream的参数,假如不传,默许就行使的体例规范失误流(sys.stderr)输出,pycharm对失误流输出的字体款式做了赤色烘托,假如换成 sys.stdout 输出的就再也不赤色了。

  

importloggingimportsyshandler=logging.StreamHandler(stream=sys.stdout)logging.basicConfig(level=logging.DEBUG,handlers=[handler])#或许指定stream参数#logging.basicConfig(level=logging.DEBUG,stream=sys.stdout)logging.info("hello")

四、奈何天生以日期光阴定名的日记?

 

  现实行使中,咱们会对日记实行归档存储,天天资成一份日记,假如哪天出了成绩,也容易定位,直接找到当天的日记文献就能够分解。咱们只要要给logger增添一个TimedRotatingFileHandler治理器就行。

  

  

file_handler=TimedRotatingFileHandler(‘logs/api.log),when="D",interval=1,backupCount=10,encoding="UTF-8",delay=False,utc=True)formatter=logging.Formatter(%(asctime)s-%(name)s-%(levelname)s-%(message)s)file_handler.setFormatter(formatter)file_handler.setLevel(logging.INFO)logger.addHandler(file_handler)

五、为甚么我日记设置后不失效?

 

  或许跟标准的加载序次相合,看个例子

  

importlogginglogger=logging.getLogger()handler=logging.StreamHandler()logger.addHandler(handler)logger.info("hello1")logger.setLevel(logging.INFO)logger.info("hello2")

 

  像下面的代码末了只输出了hello2,然而现实场景中,代码没这么简易,日常是正在a模块中的某个函数中初始化日记框架设置, 正在b模块外层创修了名字叫 logger_b的记载器,而后正在a中导入b模块时,这时日记设置还没初始化,末了招致logger_b的设置就成了默许设置。是以有或许显现日记不失效的状况。

  所以最佳践诺是能尽早初始化日记设置就尽早提前。

文章推荐:

2022 年中国人工智能行业发展现状与市场规模分析 市场规模超 3000 亿元

该来的总要来! 切尔西老板将彻底退出英国市场

雷神黑武士四代开售:i7搭RTX3060不到9千元

智慧城市中 5G 和物联网的未来