zoukankan      html  css  js  c++  java
  • 4. 为HelloWorld添加日志

    回顾

    通过上篇内容,我们已经使用flask编写了我们的第一个接口或者说是html页面。我们可以看到,使用flask来编写接口/页面是十分简单的。那么接下来,我们丰富一下上面的例子。

    需求

    现在的需求来了,在我们平时的开发过程中,总会遇到一些问题。但是又不是必现的,所以我们可以通过一些手段来写入日志,去发现问题。一个很明显的例子就是try/exception,遇到未知问题的时候可以将问题记录至日志并在事后排查。


    日志模块选用

    • logging

    我们知道,在Python中有系统自带的功能及其强大的logging模块供我们使用,它的强大不多做介绍了。网上的demo很多,稍微copy一个日志类就能使用。

    • logbook

    这里我采用的是github上的logbook库,单看api调用的话,比logging方便较多。可能因为我是个喜欢尝鲜的人_··

    安装logbook

    在终端输入pip3 install logbook并回车。

    分类

    日志模块属于Lamb的工具类,所以我将之划分到app/utils下。

    编写日志类

    import logbook
    from .. import app
    
    class Log(object):
    
        handler = None
    
        def __init__(self, name='app', filename=app.config['LOG_NAME']):    # Logger标识默认为app
            self.handler = logbook.FileHandler(filename, encoding='utf-8')
            self.logger = logbook.Logger(name)
            self.handler.push_application()
    
        def info(self, *args, **kwargs):
            return self.logger.info(*args, **kwargs)
    
        def error(self, *args, **kwargs):
            return self.logger.error(*args, **kwargs)
    
        def warning(self, *args, **kwargs):
            return self.logger.warning(*args, **kwargs)
    
        def debug(self, *args, **kwargs):
            return self.logger.debug(*args, **kwargs)
    
    

    在这里,我们定义了一个log类,这个类接受的name是日志的分类,如果不传入则默认为app,filename(日志文件名)默认值为引入app.config中配置的LOG_NAME。

    然后将logbook中的handler设为写入的文件,并将info/error/warning/debug等常用方法封装在Log类中。

    修改run.py

    from server.app import app
    from server.app.utils.logger import Log
    
    @app.route('/')
    def hello_world():
        log = Log("hello world专用")
        log.info("有人访问你的网站了")
        return 'Hello World!'
    
    
    if __name__ == '__main__':
        app.run()
    
    

    运行run.py


    进入浏览器输入http://localhost:5000

    查看logs/lamb.log文件

    image.png

    可以看到,日志文件配置生效,妈妈再也不用担心我意外出错了。


    将日志类改为单例模式(选修课)

    • 编辑utils/decorator.py
    '''
        这是一个装饰器方法文件
    '''
    
    
    class SingletonDecorator:
        def __init__(self, cls):
            self.cls = cls
            self.instance = None
    
        def __call__(self, *args, **kwds):
            if self.instance == None:
                self.instance = self.cls(*args, **kwds)
            return self.instance
    
    

    如图所示,这是一个单例类的装饰器。首先判断该类的实例是否是None,为None的话则生成新实例,否则返回该实例。这样就确保了只生成一次实例。

    当然这只是一个办法,可能在多线程的情况下会出问题。后续的优化和了解,就交给同学们自己了。

    • 给Log类加上装饰器
    import logbook
    from .decorator import SingletonDecorator     # 引入装饰器类
    from .. import app
    
     #注意这里
    @SingletonDecorator  
    class Log(object):
    
        handler = None
    
        def __init__(self, name='app', filename=app.config['LOG_NAME']):    # Logger标识默认为app
            self.handler = logbook.FileHandler(filename, encoding='utf-8')
            self.logger = logbook.Logger(name)
            self.handler.push_application()
    
        def info(self, *args, **kwargs):
            return self.logger.info(*args, **kwargs)
    
        def error(self, *args, **kwargs):
            return self.logger.error(*args, **kwargs)
    
        def warning(self, *args, **kwargs):
            return self.logger.warning(*args, **kwargs)
    
        def debug(self, *args, **kwargs):
            return self.logger.debug(*args, **kwargs)
    

    上一篇: 第一个程序Hello, World!
    下一篇: emmmmm暂时没写

    github地址: https://github.com/wuranxu/Lamb

  • 相关阅读:
    PAT Advanced 1138 Postorder Traversal (25) [树的遍历,前序中序转后序]
    PAT Advanced 1127 ZigZagging on a Tree (30) [中序后序建树,层序遍历]
    PAT Advanced 1020 Tree Traversals (25) [⼆叉树的遍历,后序中序转层序]
    PAT Basic 1075 链表元素分类(25) [链表]
    PAT A1133 Splitting A Linked List (25) [链表]
    PAT Advanced 1097 Deduplication on a Linked List (25) [链表]
    PAT Basic 反转链表 (25) [链表]
    PAT Advanced 1074 Reversing Linked List (25) [链表]
    PAT Advanced 1052 Linked List Sorting (25) [链表]
    PAT Advanced 1032 Sharing(25) [链表]
  • 原文地址:https://www.cnblogs.com/we8fans/p/9665669.html
Copyright © 2011-2022 走看看