python flask源码_Flask源码解析:Flask应用执行流程及原理

WSGI

WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述服务器端如何与web应用程序通信的规范。

Web应用程序的本质就是:

浏览器向服务器发送请求

服务器接受客户端请求,并解析

服务器端把HTML作为响应体发送给浏览器

浏览器拿取响应体渲染网页

在客户端和服务器端WSGI负责协议的转化,WSGI将web组件分为三部分:Web服务器、Web中间件、Web应用程序,当服务器接受到HTTP请求时,会按照WSGI协议解析成Request对象并调用WSGI Application,最后将响应返回给浏览器。

Werkzeug

Werkzeug是Python的WSGI规范的实用函数库。Flask使用的底层WSGI库就是Werkzeug。

WSGI 中有一个非常重要的概念:每个 Python web 应用都是一个可调用(callable)的对象。在 Flask 中,这个对象就是 app = Flask(__name__) 创建出来的 app,就是图中绿色部分。

要运行Web应用,必须依赖于Web Server,比如我们常见的Apache、Nginx、Lighttpd以及我们Flask使用的Werkzug位于黄色部分。

WSGI规定了server和app之间如何进行通信,它规定了app(environ, start_response)接口,environ是环境设置的字典,包含了请求的所有信息,start_response是WSGI处理完毕后调用的函数。

源码位置:werkzeug.serving:WSGIRequestHandler中execute()。

HelloWorld启动流程

from flask importFlask

app= Flask(__name__)

@app.route("/")defindex():return "Hello World"

if __name__ == "__main__":

app.run()

应用启动的代码: app.run()

def run(self, host=None, port=None, debug=None,

load_dotenv=True, **options):"""... 部分代码省略"""_host= '127.0.0.1'_port= 5000server_name= self.config.get('SERVER_NAME')

sn_host, sn_port=None, Noneifserver_name:

sn_host, _, sn_port= server_name.partition(':')

host= host or sn_host or_host

port= int(port or sn_port or_port)from werkzeug.serving importrun_simpletry:#导入werkzeug.serving的run_simple(),传入接受到的参数

#注意:第三个参数是self: 就是我们创建的Flask app

run_simple(host, port, self, **options)finally:

self._got_first_request= False

run_simple(host, port, self, **options)

监听指定的IP和端口,当接受到请求时,WSGI会解析,然后调用app去执行请求处理的逻辑。对应的逻辑在werkzeug.serving:WSGIRequestHandler的execute()中:

defexecute(app):#调用代码获取结果

application_iter =app(environ, start_response)try:for data inapplication_iter:

write(data)if notheaders_sent:

write(b'')finally:if hasattr(application_iter, 'close'):

application_iter.close()

application_iter= None

可以看到application_iter = app(environ, start_response),调用app执行获取响应结果。

要调用app实例,那么会调用其__call__()方法。flask.app:Flask:

def __call__(self, environ, start_response):"""The WSGI server calls the Flask application object as the

WSGI application. This calls :meth:`wsgi_app` which can be

wrapped to applying middleware."""

returnself.wsgi_app(environ, start_response)defwsgi_app(self, environ, start_response):#下篇博客讲 Flask上下文会解释,先忽略

ctx =self.request_context(environ)

error=Nonetry:try:

ctx.push()#正确的请求路径,会通过路由分发到响应的视图处理函数

response =self.full_dispatch_request()exceptException as e:

error=e

response=self.handle_exception(e)except:

error= sys.exc_info()[1]raise

returnresponse(environ, start_response)finally:ifself.should_ignore_error(error):

error=None#不管处理是否发生异常,都需要把栈中的请求 pop 出来

ctx.auto_pop(error)

上面代码业务逻辑就是通过路由配置,找到具体处理业务的视图函数。full_dispatch_request()相关代码:

deffull_dispatch_request(self):"""分派请求并在此之上执行请求处理"""self.try_trigger_before_first_request_functions()try:

request_started.send(self)

rv=self.preprocess_request()if rv isNone:

rv=self.dispatch_request()exceptException as e:

rv=self.handle_user_exception(e)return self.finalize_request(rv)

在这段中核心就是 self.dispatch_request() :

defdispatch_request(self):

req=_request_ctx_stack.top.requestif req.routing_exception is notNone:

self.raise_routing_exception(req)

rule=req.url_ruleif getattr(rule, 'provide_automatic_options', False) \and req.method == 'OPTIONS':returnself.make_default_options_response()#otherwise dispatch to the handler for that endpoint

return self.view_functions[rule.endpoint](**req.view_args)

self.dispatch_request() 返回的是处理函数的返回结果(比如Hello World 例子中返回的字符串),finalize_request 会把它转换成 Response 对象。

在 dispatch_request 之前我们看到 preprocess_request,之后看到 finalize_request,它们里面包括了请求处理之前和处理之后的很多 hooks:

before_first_request 、before_request、 after_request 、teardown_request

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值