Flask是一个非常流行的Python开源Web框架,Flask主要依赖2个库
- Jinja2
- Werkzeug, 使用python内置的BaseHTTPServer来实现wisgi,为Flask.run()默认的启动方式,但是不推荐生产环境使用
程序基本结构
from flask import Flask
from flask import request
app = Flask(__name__) # 以环境变量__name__作为程序根目录,方便后续定位静态资源
@app.route('/', methods=['GET', 'POST']) # Flask使用装饰器来定义路由
def home():
return '<h1>Home</h1>'
@app.route('/signin', methods=['GET'])
def signin_form():
return '''<form action="/signin" method="post">
<p><input name="username"></p>
<p><input name="password" type="password"></p>
<p><button type="submit">Sign In</button></p>
</form>'''
@app.route('/signin', methods=['POST'])
def signin():
# 需要从request对象读取表单内容:
if request.form['username']=='admin' and request.form['password']=='password':
return '<h3>Hello, admin!</h3>'
return '<h3>Bad username or password.</h3>'
if __name__ == '__main__':
app.run() # 使用Werkzeug来启动web服务,不适合生产环境
上下文(Context)
Flask上下文保存在globals文件中,为全局共享。看下面这个例子,我们在请求之前就引用了request这个模块,那么这个请求的信息是如何被request获取的?在多线程中,是何如做不发生冲突的?
Flask会在wsgi接口中构造上下文对象,上下文分为应用上下文与请求上下文,分别保存当前app信心与当前的请求信息。
上下文信息在线程安全的对象(werkzeug.local,相当于java中的ThreadLocal)中,FLask手动创建与释放这些对象,当一次请求到来FLask-wsgi程序按照以下顺序创建上下文:
- RequestContext(self, environ),以当前app对象(FLask实例)与请求信息(http字段构成的字典)创建一个请求上下文对象
- RequestContext.push(), 以当前app实例为参数构建AppContext(self)并放入_request_ctx_stack对象中,然后在_request_ctx_stack中放入当前请求上下文对象。
请求调度
请求调度也就是我们常说的路由,Flask会在程序的ur映射中查找请求的函数.Flask使用app.route装饰器或者非装饰器形式的app.add_url_rule()生成映射,可以获取app.url_map来查看所有url分配的规则。请求钩子
一般用来处理请求之前或者之后执行函数。比如,每次请求都之前都要发起认证请求的用户,有以下几种方式:
- before_first_request:注册一个函数,在处理第一个请求之前运行。
- before_request:注册一个函数,在每次请求之前运行
- after_request:注册一个函数,如果没有未处理的异常抛出,在每次请求之后运行
- teardown_request:注册一个函数,即使有未处理的异常抛出,也在每次请求之后运行
数据库
会话
TODO
自动将session获取与加密
https://blog.csdn.net/xiaoxinshuaiga/article/details/80766369
Q&A
1.一个http request,Flask如何处理,需要经过哪些流程?
- 构造Flask实例app,该Flask实例其实就是可执行的WSGI程序,其中call为程序入口
- 执行app.run(),校验启动参数,然后执行werkzeug.serving.run_simple()
- werkzeug中的服务继承自python内置库中的HTTPServer,HTTPServer传入会根据参数的不同来启动单进程,多线程或者多进程服务
- HTTPServer继承自内置库中的Socket_server,使用select系统调用来不停地轮序是否有新的连接
- 每当有flask捕获新的的请求会调用FLask实例app中的wsgi接口来处理请求,一个典型的wsgi为wsgi_app(environ, start_response),其中environ参数为请求的http信息
- 当一个http request到达wsgi程序的时候,flask首先应用上下文,然后构造程序上下文。同时解析请求url中并根据路由信息找到视图函数
2.signal 如何使用,什么业务场景下用?同步还是异步的?属于哪种设计模式?
参考文档:
Flask上下文: https://www.cnblogs.com/zhaopanpan/articles/9457343.html
FLask-Signal:https://www.jianshu.com/p/756ed0267f53
wsgi规范: https://www.jianshu.com/p/3fc801878e72