您好,欢迎来到12图资源库!分享精神,快乐你我!我们只是素材的搬运工!!
  • 首 页
  • 当前位置:首页 > 开发 > WEB开发 >
    Python 如何仅用 5000 行代码,完成弱小的 logging 模块?
    时间:2021-03-08 21:02 来源:网络整理 作者:网络 浏览:收藏 挑错 推荐 打印

    Python 如何仅用 5000 行代码,完成弱小的 logging 模块?

    Python 的 logging 模块完成了灵敏的日志系统。整个模块仅仅 3 个类,不到 5000 行代码的样子,学习它可以加深对顺序日志的了解,本文分下面几个部分:

    logging 简介

    logging API 设计

    记载器对象 Logger

    日志记载对象 LogRecord

    处置器对象 Hander

    格式器对象 Formatter

    滚动日志文件处置器

    小结

    小技巧

    logging 简介

    本次代码运用的是 python 3.8.5 的版本,官方中文文档 3.8.8 。参考链接中官方中文文档十分详细,建议先看一遍了解日志运用。

    类 功用
    logging-module   logging的API  
    Logger   日志记载器对象类,可以创立一个对象用来记载日志  
    LogRecord   日志记载对象,每条日志记载都封装成一个日志记载对象  
    Hander   处置器对象,担任日志输入到流/文件的控制  
    Formatter   格式器,担任日志记载的格式化  
    RotatingFileHandler   按大小滚动的日志文件记载器  
    TimedRotatingFileHandler   按时间滚动的日志文件处置器  

    我们主要研讨日志如何输入到标准窗口这一主线;日志的配置,日志的线程安全及各种特别的Handler等支线可以先疏忽。

    logging API 设计

    先看看日志运用:

    import logging 

     

    logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(name)-10s %(asctime)s %(message)s'

    lang = {"name""python""age":20

    logging.info('This is a info message %s', lang) 

    logging.debug('This is a debug message'

    logging.warning('This is a warning message'

     

    logger = logging.getLogger(__name__) 

    logger.warning('This is a warning'

    输入内容如下:

    INFO     root       2021-03-04 00:03:53,473 This is a info message {'name''python''age'20

    WARNING  root       2021-03-04 00:03:53,473 This is a warning message 

    WARNING  __main__   2021-03-04 00:03:53,473 This is a warning 

    可以看到 logging 的运用十分方便,模块直接提供了一组API。

    root = RootLogger(WARNING)  # 默许提供的logger 

    Logger.root = root 

    Logger.manager = Manager(Logger.root) 

     

    def debug(msg, *args, **kwargs): # info,warning等api相似 

        if len(root.handlers) == 0

            basicConfig()  # 默许配置 

        root.debug(msg, *args, **kwargs) 

     

    def getLogger(name=None): 

        if name: 

            return Logger.manager.getLogger(name)  # 创立特定的logger 

        else

            return root  # 前往默许的logger 

    这种API的提供方式,我们在 requests 中也有看到。api中很重要的设置config的方式:

    def basicConfig(**kwargs): 

        ... 

        if handlers is None: 

            filename = kwargs.pop("filename", None) 

            mode = kwargs.pop("filemode"'a'

            if filename: 

                h = FileHandler(filename, mode) 

            else

                stream = kwargs.pop("stream", None) 

                h = StreamHandler(stream)  # 默许的handler 

            handlers = [h] 

        dfs = kwargs.pop("datefmt", None) 

        style = kwargs.pop("style"'%'

        fs = kwargs.pop("format", _STYLES[style][1]) 

        fmt = Formatter(fs, dfs, style)  # 生成formatter 

        for h in handlers: 

            if h.formatter is None: 

                h.setFormatter(fmt) 

            root.addHandler(h)  # 设置root的handler 

        level = kwargs.pop("level", None) 

        if level is not None: 

            root.setLevel(level)  # 设置日志级别 

    可以看到,日志的配置主要包括下面几项:

    level 日志级别

    format 信息格式化模版

    filename 输入到文件

    datefmt %Y-%m-%d %H:%M:%S,uuu 时间的格式模版

    style [ % , { ,$] 格式样板

    演示代码输入中,可以看到debug日志没有显示,是由于 debug < info :

    CRITICAL = 50 

    FATAL = CRITICAL 

    ERROR = 40 

    WARNING = 30 

    WARN = WARNING 

    INFO = 20 

    DEBUG = 10 

    NOTSET = 0 

    记载器对象 Logger

    查看Logger之前,先看logger对象的管理类Manager

    _loggerClass = Logger 

     

    class Manager(object): 

        def __init__(self, rootnode): 

            self.root = rootnode 

            self.disable = 0 

            self.loggerDict = {}  # 一切日志记载对象的字典 

        ... 

        def getLogger(self, name): 

            rv = None 

            if name in self.loggerDict: 

                rv = self.loggerDict[name]  # 获取曾经创立过的同名logger 

                ... 

            else

                rv = (self.loggerClass or _loggerClass)(name)  # 创立新的logger 

                rv.manager = self 

                self.loggerDict[name] = rv 

                ... 

            return rv 

    日志过滤器

    class Filterer(object): 

     

        def __init__(self): 

            self.filters = [] 

     

        def addFilter(self, filter): 

            self.filters.append(filter) 

     

        def removeFilter(self, filter): 

            self.filters.remove(filter) 

     

        def filter(self, record): 

            rv = True 

            for f in self.filters:  # 过滤日志 

                if hasattr(f, 'filter'): 

                    result = f.filter(record) 

                else

    (责任编辑:admin)