给Hello World添加日志

回顾

通过上篇内容,我们已经使用「Flask」完成了我们的第一个接口。我们可以看到,使用「Flask」来编写接口是十分简单的。那么接下来,我们丰富一下上面的例子。

需求

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


日志模块选用

logging

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

logbook

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

安装logbook

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

分类

日志模块属于pity的工具类,笔者将之划分到app/utils下。

编写日志类

import logbook

from app import pity

class Log(object):
    handler = None

    def __init__(self, name='pity', filename=pity.config['LOG_NAME']):  # Logger标识默认为app
        """
        :param name: 业务名称
        :param filename: 文件名称
        """
        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是日志的分类,如果不传入则默认为「pity」,filename(日志文件名)默认值为引入config.py中配置的「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


报错截图

发现居然报错了,我们仔细查看下控制台:


控制台报错信息

看提示是「没有找到对应的文件或目录」, 原来我们的pity目录下没有「logs」目录, 而这种日志库一般也不会帮忙创建目录,所以我们暂时手动在pity目录下建立logs目录即可。

建立以后重启服务, 「再次尝试」


成功截图

查看logs/pity.log文件

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


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

  • 编辑utils/decorator.py
'''
    这是一个装饰器方法文件
'''

class SingletonDecorator:
    def __init__(self, cls):
        self.cls = cls
        self.instance = None

    def __call__(self, *args, **kwds):
        if self.instance is None:
            self.instance = self.cls(*args, **kwds)
        return self.instance

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

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

  • 给Log类加上装饰器
import logbook

from app import pity
from .decorator import SingletonDecorator

# 注意这里
@SingletonDecorator
class Log(object):
    handler = None

    def __init__(self, name='pity', filename=pity.config['LOG_NAME']):  # Logger标识默认为app
        """
        :param name: 业务名称
        :param filename: 文件名称
        """
        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)

作业

发现一个小问题,日志的时间似乎不对,可能是哪里出了问题呢?

全部代码地址: https://github.com/wuranxu/pity

「觉得有用的话可以帮忙点个Star哦QAQ」

测试平台系列(3) 给Hello World添加日志的更多相关文章

  1. 测试平台系列(85) 把redis运用到实战中

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们让支持了前置条件 ...

  2. 测试平台系列(2) 给Pity添加配置

    给Pity添加配置 回顾 还记得上篇文章创立的「Flask」实例吗?我们通过这个实例,给根路由 「/」 绑定了一个方法,从而使得用户访问不同路由的时候可以执行不同的方法. 配置 要知道,在一个「Web ...

  3. 测试平台系列(71) Python定时任务方案

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 定时任务 定时任务,顾名思义: ...

  4. 测试平台系列(72) 了解ApScheduler基本用法

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们调研了一下市面上 ...

  5. 测试平台系列(79) 编写Redis配置功能(下)

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们提出了优化Dao ...

  6. 测试平台系列(90) 编写oss客户端

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程,希望大家多多支持. 欢迎关注我的公众号米洛的测开日记,获取最新文章教程! 回顾 上一节我们编写了在线执行测试 ...

  7. 测试平台系列(92) 让http请求支持文件上传

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程,希望大家多多支持. 欢迎关注我的公众号米洛的测开日记,获取最新文章教程! 回顾 上一节呢,我们编写了oss的 ...

  8. 测试平台系列(55) 引入AceEditor(代码编辑器)

    大家好,我是米洛,求三连!求关注测试开发坑货! 回顾 我们上一节已经写好了左侧数据表目录,今天继续完成sql编辑器的部分. 调研组件 monaco 因为我们的项目用的是React,市面上很多编辑器都是 ...

  9. 测试平台系列(80) 封装Redis客户端

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们编写了Redis ...

随机推荐

  1. AbstractQueuedSynchronizer的使用和juc里的相关类的解析

    对AQS进行解析后,先来实现两个简单的基于AQS的类,然后再解析juc里基于AQS构造的类. 1.基于AQS的类的示例 首先先看这个类,这个类是<Java并发编程实战>的一个示例,AQS源 ...

  2. Github markdown页面内跳转

    基本操作: 请看这里 最典型的就是[alt_content](#jump) 但有时, jump是不太好直接看出来的, 比如下面这个标题, 格式复杂, 那如何获取相应的jump呢? 在Github中, ...

  3. certbot 获取数字证书失效问题

    title: certbot 获取数字证书失效问题 author: Narule date: 2021-02-18 10:45:00 +0800 categories: [Technology^技术, ...

  4. How to get the real screen size(screen resolution) by using js

    How to get the real screen size(screen resolution) by using js 获取用户屏幕的真实像素分辨率, 屏幕实际尺寸 window.deviceP ...

  5. 使用 js 实现一个简易版的 vue 框架

    使用 js 实现一个简易版的 vue 框架 具有挑战性的前端面试题 refs https://www.infoq.cn/article/0NUjpxGrqRX6Ss01BLLE xgqfrms 201 ...

  6. 图解 HTTP, 图解 HTTPS, 图解 HTTP/2, 图解 HTTP/3, 图解 QUIC

    图解 HTTP, 图解 HTTPS, 图解 HTTP/2, 图解 HTTP/3, 图解 QUIC HTTP https://en.wikipedia.org/wiki/Hypertext_Transf ...

  7. 析构函数 & 构造函数

    析构函数 & 构造函数 C++ 析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数. 析构函数往往用来做"清理 ...

  8. mdn & remove & removeChild

    mdn & remove & removeChild Element https://developer.mozilla.org/en-US/docs/Web/API/Element ...

  9. js showOpenFilePicker showSaveFilePicker showDirectoryPicker API

    选择文件,获取文件句柄 btn.addEventListener("click", async (e) => { try { const hFiles = await win ...

  10. NGK内存爆发式增长,看Baccarat将怎样打造全新的全场景金融生态

    从数字货币抵押借贷业务出发,DeFi已经形成了覆盖全场景的全新金融生态. 可以说,除了信贷等少数对现实世界信息存在较多依赖的实体业务,DeFi已经实现了传统金融业务的全面链上迁移.大多数传统金融行业存 ...