Flask 源码剖析
flask 是一个基于 Python 开发的 wsgi 微型框架。flask 有两个核心依赖库:Werkzug
和jinjia
。其中werkzeug
负责核心的逻辑模块,比如路由、请求和应答的封装、WSGI 相关的函数等;jinja
负责模板的渲染,主要用来渲染返回给用户的 html
文件内容。
1.入口
web 程序都是从服务器通过相关wsgi
在转换的相关的程序中,Django 中一直使用的是此种方式,Django 3.x 及以后的版本加入了ASGI
通过异步进行请求的处理。
flask 中内部使用的是 Werkzug 模块进行的处理。
1.1 Werkzug 的介绍与使用
werkzueg是一个优秀的工具库,使用werkzueg实现一个符合WSGI协议的web 应用程序
面向对象知识的补充:
class Base:
def __call__(self, *args, **kwargs):
print("call 执行了")
def func(self):
print("func ...")
obj = Base()
# obj()
obj.func()
简单使用
from werkzeug import run_simple
def func(environ,start_response):
# 改函数需要写上这两个参数,因为源码内部需要这两个值
print("请求来了")
if __name__ == '__main__':
# app.run()
run_simple("127.0.0.1",5000,func)
>>> 点击请求地址(请求过来时)
>>> 请求来了
>>> 报错
# 函数被执行相当于 func()
通过以上的例子可以看到,当点击请求地址时(请求过来时),通过werkzug
启动了一个小的 web 程序,并去执行相关的函数。当我们把函数换做类进行尝试。
from werkzeug import run_simple
class FlaskBase:
def __call__(self, *args, **kwargs):
print("call方法执行了")
app = FlaskBase()
if __name__ == '__main__':
# app.run()
run_simple("127.0.0.1",5000,app)
>>> 点击请求地址
>>> call 方法被执行了
>> 报错
特别注意:当点击请求地址时(请求过来时),通过这个可以发现将对象传入,相当于执行了对象()
,因此出入的值回去执行类对应的__call__
方法。
werkzug启动flask
from flask import Flask
from werkzeug import run_simple
app = Flask(__name__)
if __name__ == '__main__':
run_simple("127.0.0.1",5000,app)
- werkzug 中可以将一个小的 flask 应用直接启动。
1.2 简单的 Flask 网站
# 最简单的 flask 应用
from flask import Flask
app = Flask(__name__)
if __name__ == '__main__':
app.run()
flask 的启动中执行了run()
方法。
# Flask内部源码:run方法内部的部分源码
from werkzeug.serving import run_simple
try:
run_simple(t.cast(str, host), port, self, **options)
# 此处传入主要有三个参数:地址、端口号、对象。
# 特别说明:此处的对象为在外面已经实例化好的对象,即 app
# 根据以上研究,请求过来时,会执行flask 的__call__方法。
finally:
# reset the first request information if the development server
# reset normally. This makes it possible to restart the server
# without reloader and that stuff from an interactive shell.
self._got_first_request = False
flask 内部中的__call__()
方法
def __call__(self, environ: dict, start_response: t.Callable) -> t.Any:
"""The WSGI server calls the Flask application object as the
WSGI application. This calls :meth:`wsgi_app`, which can be
wrapped to apply middleware.
"""
# 这里会看到这个函数中也有这两个参数 environ,start_response
return self.wsgi_app(environ, start_response)
- 通过源码内部的方法可以看出,Flask 启动的本质上执行的还是
Werkzug.run_simple()
函数,进行 web 程序的启动。
结论:
- flask 由 werkzug 进行启动,本质上执行的是
Werkzug.run_simple()
函数。 - 重要:flask 中,请求到来时,执行的是对象的
__call__()
方法
天雨虽宽,不润无根之。学习虽难,勤奋可达巅峰;
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/275763.html