zoukankan      html  css  js  c++  java
  • logging 模块

     在深入学习装饰器时,发现log日志实例,才发现之前对于logging模块的理解实在是浅了,于是打算好好整理一篇来记录logging,用优雅的方式来解决程序日志记录的问题。

     logging 相比print的优势:

    • 可以在 logging 模块中设置日志等级,在不同的版本(如开发环境、生产环境)上通过设置不同的输出等级来记录对应的日志,非常灵活。
    • print 的输出信息都会输出到标准输出流中,而 logging 模块就更加灵活,可以设置输出到任意位置,如写入文件、写入远程服务器等。
    • logging 模块具有灵活的配置和格式化功能,如配置输出当前模块信息、运行时间等,相比 print 的字符串格式化更加方便易用。

    logging框架中主要由四个部分组成:

    • Loggers: 可供程序直接调用的接口
    • Handlers: 决定将日志记录分配至正确的目的地
    • Filters: 提供更细粒度的日志是否输出的判断
    • Formatters: 制定最终记录打印的格式布局

    先看一个初步用法,了解一下大概:

    import logging
    
    
    logging.basicConfig(filename='mylog.log', filemode="w", level=logging.INFO)
    logging.debug('debug message')
    logging.info('info message')
    logging.warn('warn message')
    logging.error('error message')
    logging.critical('critical message')

    logging.basicConfig

    • filename:即日志输出的文件名,如果指定了这个信息之后,实际上会启用 FileHandler,而不再是 StreamHandler,这样日志信息便会输出到文件中了。
    • filemode:这个是指定日志文件的写入方式,有两种形式,一种是 w,一种是 a,分别代表清除后写入和追加写入。
    • format:指定日志信息的输出格式,即上文示例所示的参数,详细参数可以参考:docs.python.org/3/library/l…,部分参数如下所示:
      • %(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。
      • %(processName)s:打印线程名称。
      • %(module)s:打印模块名称。
      • %(message)s:打印日志信息。
    • datefmt:指定时间的输出格式。
    • style:如果 format 参数指定了,这个参数就可以指定格式化时的占位符风格,如 %、{、$ 等。
    • level:指定日志输出的类别,程序会输出大于等于此级别的信息。
    • stream:在没有指定 filename 的时候会默认使用 StreamHandler,这时 stream 可以指定初始化的文件流。
    • handlers:可以指定日志处理时所使用的 Handlers,必须是可迭代的

    logged装饰器

    这里我们实现了一个带参数的装饰器,也是一个很好的装饰器的学习例子。

    from functools import wraps
    import logging
    
    
    def logged(level, name=None, message=None):
        """
        Add logging to a function. level is the logging
        level, name is the logger name, and message is the
        log message. If name and message aren't specified,
        they default to the function's module and name.
        """
        def decorate(func):
            logname = name if name else func.__module__
            log = logging.getLogger(logname)
            logmsg = message if message else func.__name__
    
            @wraps(func)
            def wrapper(*args, **kwargs):
                log.log(level, logmsg)
                return func(*args, **kwargs)
            return wrapper
        return decorate 

    应用

    import logging
    from log import logged
    logging.basicConfig(filename='output.log',
                        filemode="w",
                        level=logging.INFO,
                        datefmt='%Y/%m/%d %H:%M:%S',
                        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    
    class Demo:
        @logged(logging.INFO,name="demo",message="run rabbit")
        def run(self):
            print("run")
    
        @logged(logging.INFO, name="demo", message="sleep")
        def sleep(self):
            print("sleep")
    
        @logged(logging.INFO, name="demo", message="!-- stated --!")
        def main(self):
            self.run()
            self.sleep()
    
    
    if __name__ == "__main__":
        Demo().main()
    

      只需要我们装饰需要输出日志的函数即可,自定义输出内容。

    然鹅 logging 是不支持多进程的,或者即使支持多进程那么日志的顺序也会被打乱,也是不可行的。

    个人解决方案很粗暴:

    需要将logging.basicConfig初始化函数写在实例化类的run(入口函数中),

    因为实际多进程的进程是该函数,而不应该写在实例化类的__init__函数中。

  • 相关阅读:
    Use jQuery to hide a DIV when the user clicks outside of it
    Backbone
    重学HTML
    javaScript return false
    Regular Expression--Good parts
    ASP.NET批量下载文件的方法
    ASP.NET多文件批量打包下载
    word图文混排复制到UEditor图片不显示
    百度ueditor 拖文件或world 里面复制粘贴图片到编辑中 上传到第三方问题
    Ueditor Word图片转存交互
  • 原文地址:https://www.cnblogs.com/zenan/p/8710250.html
Copyright © 2011-2022 走看看