flask源码分析-框架扩展(六)

良好的框架应该有良好的扩展性

试想我有如下需求:

  • 在服务器启动时,我需要往数据库初始化一些数据
  • 在每次请求api之前,需要验证用户token是否合法
  • 每次请求完成后,需要往数据库插入一条日志

你可能会这么做,我先去找到服务器启动时的代码位置,在他之前插入一段代码;
在请求分发到路由之前,我找到源码的位置,然后再此处插入一段代码。。。。。。

如果一个框架不在某些位置留几个口子留给你扩展的话,必须继承原来的类进行扩展,甚至重写覆盖方法都无法完成需求时,那么这不是一个成熟的框架;良好的框架设计时就已经预埋了扩展点,比如我们mes后端代码基类里的,before_save_one,before_delete_one等等,类似这种概念

我总结了在flask框架中留给用户扩展的两种方式:

  • 钩子函数:把你需要执行的函数全部注册进来,框架会在运行到此处时帮你一一执行
  • 信号机制:

钩子函数

钩子函数是指在执行函数和目标函数之间挂载的函数,框架开发者给调用方提供一个point-挂载点,至于挂载什么函数由调用方决定

from flask import Flask, request,session
from flask import signals

app = Flask(__name__)

@app.before_first_request
def fun1():
    print('启动服务器时执行,里面做了一个标识,后面就不会再执行了')


@app.before_request
def fun2():
    print('每次请求之前都会执行')

@app.after_request
def fun3(response):
    print('每次请求之后执行,传入一个response对象')
    return response

@app.teardown_request
def fun4(exc):
    print('含泪执行,无论如何都会执行')
	

@app.errorhandler(404)
def errorhandler(e):
    # 当访问一个不存在的url时
    return '出错啦!'

@app.route('/')
def index():
    return '12'

if __name__ == '__main__':
    app.run(debug=True)

信号机制

  • 概念:信号就是在框架核心功能或者一些Flask扩展发生工作时所发送的通知,用于帮助你解耦应用
  • 你可以认为是当你在环游全球时,每到达一个国家,你发一个朋友圈打卡,广播告诉你的朋友们你到了,然后看到你的朋友圈的朋友开始给你回复。
  • 信号看起来和钩子做类似的事情
  • 信号依赖于Blinker库,但是也可以使用flask封装的namespace避免安装blinker库

blinker使用示例

from blinker import signal

# 信号发布者
s1 = signal('s1')

# 订阅者1号
def func1(sender):
    print(sender)

# 订阅者2号
def func2(sender):
    print(sender)

s1.connect(func1, sender=1) # sender为1时,订阅号一号才会执行
s1.connect(func2)

for i in range(3):
    s1.send(i)

flask信号使用示例

from flask import Flask, request,session
from flask.signals import request_started,request_finished

app = Flask(__name__)


def fun1(app):
    print(app)
    print('每次请求之前都会执行')

def fun2(*args, **kwargs):
    print(args,kwargs)
    print('每次请求完成之后执行,传入一个response对象')

request_started.connect(fun1)
request_finished.connect(fun2)

@app.route('/')
def index():
    return '12'

if __name__ == '__main__':
    app.run(debug=True)

总结

  • 信号看起来和钩子做同样的事情。然而在工作方式上它们存在不同。譬如核心的before_request()处理程序以特定的顺序执行,并且可以在返回响应之前放弃请求。相比之下,所有的信号处理器是无序执行的,并且不修改任何数据,并且无法中断请求。
  • 一般来说,钩子用于改变行为(比如,身份验证或错误处理),而信号用于记录事件(比如记录日志)
  • 此处可以到源码中找一些信号埋放的位置,展示给大家看

你可能感兴趣的:(flask源码分析,flask,框架,源码分析)