创建一个为视图访问加日志的扩展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 setup setup(
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 = app
if 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 ret return 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 Logging app = 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版本

Flask 扩展 自定义扩展的更多相关文章

  1. Python flask 构建可扩展的restful apl☝☝☝

    Python flask 构建可扩展的restful apl☝☝☝ Flask-RESTful是flask的扩展,增加了对快速构建REST API的支持.Flask-RESTful通过最少的设置鼓励最 ...

  2. flask 之(四) --- 扩展|缓存|会话

    扩展 蓝图内置扩展 (实现的是路由的拆分) '''----------- app.py -------------''' from flask import Flask from users_view ...

  3. SharePoint 2013 自定义扩展菜单

    在对SharePoint进行开发或者功能扩展的时候,经常需要对一些默认的菜单进行扩展,以使我们开发的东西更适合SharePoint本身的样式.SharePoint的各种功能菜单,像网站设置.Ribbo ...

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

    接博文<SharePoint 2013 自定义扩展菜单>,多加了几个例子,方便大家理解. 例七 列表设置菜单扩展(listedit.aspx) 扩展效果 XML描述 <CustomA ...

  5. WCF自定义扩展,以实现aop!

    引用地址:https://msdn.microsoft.com/zh-cn/magazine/cc163302.aspx  使用自定义行为扩展 WCF Aaron Skonnard 代码下载位置: S ...

  6. Jquery自定义扩展方法(二)--HTML日历控件

    一.概述 研究了上节的Jquery自定义扩展方法,自己一直想做用jquery写一个小的插件,工作中也用到了用JQuery的日历插件,自己琢磨着去造个轮子--HTML5手机网页日历控件,废话不多说,先看 ...

  7. Silverlight实例教程 - 自定义扩展Validation类,验证框架的总结和建议(转载)

    Silverlight 4 Validation验证实例系列 Silverlight实例教程 - Validation数据验证开篇 Silverlight实例教程 - Validation数据验证基础 ...

  8. jQuery 自定义扩展,与$冲突处理

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. SparkContext自定义扩展textFiles,支持从多个目录中输入文本文件

    需求   SparkContext自定义扩展textFiles,支持从多个目录中输入文本文件   扩展   class SparkContext(pyspark.SparkContext): def ...

随机推荐

  1. canvas焰火特效

    之前在抖音上看到了一个很漂亮的焰火效果.这会儿有时间就用canvas实现了一下. 演示地址:http://suohb.com/work/firework4.htm 先看效果:(静态图片看不太出效果,请 ...

  2. RLS自适应滤波器中用矩阵求逆引理来避免求逆运算

    在RLS自适应滤波器的实现过程中,难免不涉及矩阵的求逆运算.而求逆操作双是非常耗时的,一个很自然的想法就是尽可能的避免直接对矩阵进行求逆运算.那么,在RLS自适应滤波器的实现中,有没有一种方法能避免直 ...

  3. SA 后缀数组

    SA 后缀数组 首先一定要确定\(SA\)是个什么东西 \(SA[i]\)表示的是排名为\(i\)的后缀是哪一个 至于后缀\(i\)的排名是多少,那个是\(rank[i]\) 当然啦 最最最难懂的就是 ...

  4. 【SPOJ】Longest Common Substring II (后缀自动机)

    [SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记 ...

  5. Bzoj1176:Mokia&Cogs1752:[BOI2007]摩基亚Mokia

    题目 Cogs 没有Bzoj的权限号 Sol 离线,\(CDQ\)分治,把询问拆成\(4\)个,变成每次求二位前缀和 那么只要一个修改操作(关键字为时间,\(x\),\(y\))都在这个询问前,就可以 ...

  6. [BZOJ1552] [Cerc2007] robotic sort (splay)

    Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号. Output ...

  7. oracle数据库和表的操作

    一.字符函数 (1)连接符 concat --连接符 select concat('10086','-')||'1531234567' 电话号 from dual; (2)首字母大写 initcap ...

  8. 论文笔记(1):From Image-level to Pixel-level Labeling with Convolutional Networks

    文章采用了多实例学习(MIL)机制构建图像标签同像素语义的关联 . 该方法的训练样本包含了70 万张来自ImageNet的图片,但其语义分割的性能很大程度上依赖于复杂的后处理过程,主要包括图像级语义的 ...

  9. 了解wireshark

    Wireshark是很流行的网络分析工具.这个强大的工具可以捕捉网络中的数据,并为用户提供关于网络和上层协议的各种信息.与很多其他网络工具一样,Wireshark也使用pcap network lib ...

  10. 【技术】关于安卓使用禁用服务(或者是MYANDROIDTOOLS里面的禁用服务)后卡在开机页面的(或者是卡在各种页面的)

    目前会出现禁用部分服务后卡在开机页面,导致到手机数据得全部清除在网上找了很久,都没找到还原的方法只好自己开垦新方案了推测:由于格式化DATA分区后,手机可以正常开机,所以认为禁用服务的配置内容保存在D ...