创建一个为视图访问加日志的扩展Flask-Logging,并从中了解到写Flask扩展的规范。

创建工程

先创建一个工程,目录结构如下:

flask-logging/├ LICENSE           # 授权说明├ README            # 项目介绍├ setup.py          # 打包分发文件└ flask_logging/    # 扩展代码包└ __init__.py   # 扩展代码

根据Flask扩展命名规范,扩展名必须为”Flask-Logging”形式,以”Flask-“为前缀,后面的单词首字母大写。扩展的代码必须放在名为”flask_logging”的包下,注意这里是下划线,与扩展名中的横线不同,单词都小写。”LICENSE”和”README”文件都是审核必须的,关于审核部分,我们会在后面介绍。

编写分发文件

接下来,我们写”setup.py”文件,示例如下:

"""
Flask-Logging
-------------Log every request to specific view
"""
from setuptools import setupsetup(name='Flask-Logging',version='1.0',url='http://example.com/flask-logging/',license='BSD',author='Billy J. Hee',author_email='billy@bjhee.com',description='Log every request to specific view',long_description=__doc__,packages=['flask_logging'],zip_safe=False,include_package_data=True,platforms='any',install_requires=['Flask'],classifiers=['Environment :: Web Environment','Intended Audience :: Developers','License :: OSI Approved :: BSD License','Operating System :: OS Independent','Programming Language :: Python','Topic :: Internet :: WWW/HTTP :: Dynamic Content','Topic :: Software Development :: Libraries :: Python Modules']
)

这里需要注意几点:

  • 扩展名的格式必须为”Flask-Logging”,上节介绍过
  • 必须指定url链接到扩展主页或文档
  • “zip_safe”必须为False
  • “install_requires”必须列出所有依赖的库

编写扩展代码

进入主题了,由于我们的扩展相当简单,因此所有代码都放在了”__init__.py”中:

#coding:utf8
from flask import current_app, request
from functools import wraps
from logging.handlers import TimedRotatingFileHandler
import logging
import time# 指定日志文件名,日志级别,及日志记录格式
entry_log = TimedRotatingFileHandler('entry.log','D')
entry_log.setLevel(logging.DEBUG)
entry_log.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s'))class Logging:# 构造函数def __init__(self, app=None):self.app = appif app is not None:self.init_app(app)# 初始化应用def init_app(self, app):app.logger.addHandler(entry_log)# 视图装饰器,被装饰的视图将自动记录访问日志def log_entry(self, func):app = self.app or current_app@wraps(func)def decorator(*args, **kwargs):start = time.time()# 记录请求开始app.logger.debug('Start request call: %s' % request.url)ret = func(*args, **kwargs)# 记录请求结束app.logger.debug('Finish request call: %s' % request.url)duration = time.time() - start# 记录请求所耗时长app.logger.debug('Request: %s consumed %f s' % (request.url, duration))return retreturn decorator

代码逻辑都在写注释里了,这个扩展提供了”log_entry”视图装饰器,来记录视图访问日志。这里同样要注意几个重要的部分:

  1. 构造函数”__init__()”和初始化函数”init_app()”是必须的
  2. 如果构造函数传入了app,则调用”init_app()”,这样确保两者功能一致
  3. 构造函数里我们设置了”self.app=app”,而”init_app()”没有,这是为什么呢?这是一种规范,或者说习惯。当系统只有一个app时,建议使用构造函数初始化扩展对象,这时对象中的app就指向这一个应用。而当系统有多个应用同时存在,比如说应用工厂或测试场景下,建议使用”init_app()”来初始化扩展对象,这样扩展对象不会指向任何应用
  4. 在视图装饰器里,我们使用了”app = self.app or current_app”来获取当前应用,这分别对应于上一点说的单个应用及多个应用场景
  5. 因为视图装饰器是视图访问时被调用,所以此时应用上下文和请求上下文都存在,因此我们可以访问到”current_app”和”request”对象。离开上下文的话,就无效了

扩展写完了,让我们来测试一下,创建一个Flask应用:

from flask import Flask
from flask_logging import Loggingapp = Flask(__name__)
logging = Logging(app)@app.route('/')
@logging.log_entry
def index():return '<h1>Hello World</h1>'if __name__ == '__main__':app.run(host='0.0.0.0', debug=True)

启动应用,访问”http://localhost:5000/”。查看下代码当前路径,是不是出现了”entry.log”文件,并且记录了URL请求日志

关于审核

如果要将自己的扩展提交官方审核,至少要做到下面几点:

  1. 扩展代码在包”flask_myext”下,审核通过后,Flask会设置一个重定向包”flask.ext.myext”来指向你的包。对于用户来说,官方扩展建议导入”flask.ext.myext”格式的包
  2. 必须提供一个”setup.py”分发文件,并在PyPI上注册,这样用户就可以通过”pip install”来安装你的扩展
  3. 必须提供”LICENSE”文件,并且授权是BSD, MIT或WTFPL
  4. 必须提供”README”文件及文档,文档是由Sphinx生成
  5. 必须同时提交单元测试代码
  6. 必须支持Python 2.6和2.7版本

转载于:https://www.cnblogs.com/Erick-L/p/7061669.html

Flask 扩展 自定义扩展相关推荐

  1. VS Code 安装 Go 插件、自定义扩展配置、断点调试

    1. 安装插件 使用快捷键 Ctrl+Shift+X 打开插件安装页面,安装 Go 插件. 2. 自定义扩展配置 使用快捷键 Ctrl+, 打开自定义配置页,编辑 settings.json ,定义与 ...

  2. 2022还在使用Mysql进行数据检索?ElasticSearch自定义扩展词库完成检索

    文章目录 1.为什么要自定义扩展ES词库呢? 2.如何自定义扩展词库呢? 3.Docker安装Nginx 4.在nginx中保存一个简易词库 5.修改IK分词器的配置文件,让其指向nginx保存的词库 ...

  3. python interpreter 中没有torch_PyTorch扩展自定义PyThon/C++(CUDA)算子的若干方法总结

    在做毕设的时候需要实现一个PyTorch原生代码中没有的并行算子,所以用到了这部分的知识,再不总结就要忘光了= =,本文内容主要是PyTorch的官方教程的各种传送门,这些官方教程写的都很好,以后就可 ...

  4. class ts 扩展方法_JUnit 5自定义扩展

    前言 在org.junit.jupiter.api.extension包下,JUnit5提供了丰富的扩展接口,通过实现这些接口,我们可以定制自己的扩展并注册到JUnit中来实现功能扩展. Extens ...

  5. SharePoint 2013 自定义扩展菜单(二)

    转载自:http://www.cnblogs.com/jianyus/p/3376075.html 包含另外三个例子,列表设置.管理中心.人员和组添加菜单 接博文<SharePoint 2013 ...

  6. Nacos自定义扩展的 Data Id 配置

    Spring Cloud Alibaba Nacos Config可支持自定义 Data Id 的配置. 一个完整的配置案例如下所示: 下边我们在service2微服务下配置扩展. spring:ap ...

  7. Django扩展自定义manage命令

    使用django开发,对python manage.py ***命令模式肯定不会陌生.比较常用的有runserver,migrate... 本文讲述如何自定义扩展manage命令. 1.源码分析 ma ...

  8. ETL作业调度软件TASKCTL自定义扩展作业类型插件安装

    TASKCTL批量自动化调度作业类型扩展插件的安装方法如下几种: 1. 直接覆盖法 直接覆盖法的意思就是将自定义扩展好的插件,通常是一个shell脚本,上传至后台调度核心服务上,然后修改后台任务类型的 ...

  9. 使用C#为.NET Interactive开发自定义扩展

    在前面的文章中,我们介绍了如何在.NET Interactive notebook绘制图表和执行SQL. 那么,能不能为.NET Interactive开发交互功能呢? 今天,我们就来演示如何实现. ...

  10. ASP.NET 3.5核心编程学习笔记(55):自定义扩展程序控件的创建

    ASP.NET并没有包含对扩展程序的具体实现.然而,它定义了供所有自定义扩展程序和ACT中所有扩展程序使用的基类ExtenderControl.我们可通过该类创建自己的扩展程序.但并不建议这样做,因为 ...

最新文章

  1. 引入外部css_css
  2. AI在管理临床试验设计和执行中,人和机器还在学习曲线上?
  3. 数据库mongodb和mysql对比
  4. SAP实施不成功就像女人丰乳没效果
  5. JavaScript操作DOM元素
  6. python中扑克牌类设计_Python类的基础设计、使用
  7. Vue生命周期详解 对应代码解析
  8. 计算机应用技术研究生开题报告,计算机应用技术专业论文开题报告.doc
  9. 【长沙集训】2017.10.28
  10. DynamicFusion: Reconstruction and Tracking of Non-rigid scenes in real-time
  11. Dynamics 365Online 模板(Template)可以下载了
  12. BUUCTF misc 解题记录 一(超级详细)
  13. AHCI和IDE的区别,如何在AHCI模式下安装系统
  14. 基于层次分析法(AHP)的信贷案例详解
  15. DBF文件初步了解(二)——DBF数据导出代码实现
  16. 无线渗透(下)—企业级WPA破解
  17. ios系统脚本服务器加速,让iOS系统加速飞起来 speed intensifier插件让iOS系统加速
  18. 小白编译AnyQ-dockerlinux[CentOs]——AnyQ系列之一
  19. 道一时间转换工具发布
  20. POE受电设备(PD)电路工作原理

热门文章

  1. 洛谷 P1114 “非常男女”计划
  2. linux SVN web 同步
  3. MySQL存储过程定时任务
  4. CMD获取当前目录的绝对路径
  5. 清除SQLServer2008缓存
  6. JavaScript 实现模拟拖放
  7. SQL Server2005完全版与精简版的一个差别(抄录)
  8. servlet三种方式实现servlet接口
  9. LOJ2336 JOI2017 绳 贪心、构造
  10. 硬件开发者之路之——保护电路系列之输入电源端口的防护设计