flask应用启动

124 篇文章 0 订阅

一开始就知道这样运行一个flask 应用

首先,在编辑器中写flask 应用代码:

这里写图片描述

然后,在计算机命令行运行自己写的 flask 模块:

这里写图片描述

在浏览器中输入网址,发现网页显示了flaskapp 中index函数的返回值内容:

这里写图片描述

这时候,命令行中也发生了一些改变:

这里写图片描述



根据这几天的学习flask 源码,大致知道了上面操作的原理。

下图显示了python中客户端、服务器、WSGI、应用之间的关系:
(1) Application 这里就是需要运行的flaskapp,即实例化的app
(2) 在命令行中运行flaskapp 模块是创建WSGI server 就是这里的服务器。
(3) 客户端这里就是浏览器。
(4) 浏览器中输入网址,即发送请求到服务器,会触发wsgi_app来处理请求(命令行中的 GET /表示获取endpoint为’/’的视图函数,200表示OK,处理正常),最后将处理结果返回给客户端。

这里写图片描述



再完整一些的流程:
(1)命令行中 python flaskapp.py 运行, flaskapp.py模块,逐行运行 flaskapp.py中的代码。

(2) app = Flask(__name__)实例化一个Flask 对象,__name__为当前模块名。

(3) @app.route("/") 使用了装饰器,和add_url_rule性质一样。功能是添加endpoint( ‘/’)和view_func(’index’)的映射关系到view_functions字典中。

(4) if __name__ == '__main__': 保证当前模块是被直接运行,而不是被其他模块导入,然后在运行之后的代码。

(5) app.run(debug=True) 在本地服务器上运行flask 应用,同时传递了debug=True参数。

(6) run(self, host=None, port=None, debug=None, **options)self就是实例化了的 app,运行run()之后,会设置host = '127.0.0.1', port = 5000

(7)run()方法中 run_simple(host, port, self, **options) 运行之后会创建一个本地服务器。

(8) 设置默认的_got_first_request = False,表明服务器还没有收到客户端的请求。

(9) run_simple()100多行,那些提示消息(*Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) 等)也是在run_simple()中设置的。重要的是这么一句srv = make_server(...),在这儿创建了本地服务器。

(10) 根据前面传递的参数,make_server(...)返回了一个单进程单线程的WSGI server,即BaseWSGIServerBaseWSGIServer继承了HTTPServerHTTPServer继承了TCPServerTCPServer继承了BaseServer。不考虑细节,就是创建了本地服务器,同时,本地服务器已经记录了flaskapp信息。

(11) WSGI server的功能:监听指定的端口,收到 HTTP 请求的时候解析为 WSGI 格式,然后调用 app 去执行处理的逻辑。


再看从客户端输入网址,到看到网页响应的过程:

(1) 客户端发送请求到 WSGI server,WSGI server使用__call__ 方法来调用 app处理请求,__call__方法返回了wsgi_app(environ, start_response),即使用wsgi_app(self, environ, start_response) 处理请求并将处理结果返回到服务器,再返回到客户端。

(2) 从BaseWSGIServer中的定义开始看:
BaseWSGIServer中有行代码是handler = WSGIRequestHandler,即收到客户端的请求后,本地的 WSGI server使用WSGIRequestHandler来处理请求。

(3) WSGIRequestHandler 有个重要的方法是make_environ(self),返回一个environ字典。可以创建一个供app 运行的环境。

(4) 然后看WSGIRequestHandler 中的 handle_one_request()方法。handle_one_request()中关键的run_wsgi(),看名字,运行wsgi

(5) WSGIRequestHandler继承自BaseHTTPRequestHandlerBaseHTTPRequestHandler继承自StreamRequestHandlerStreamRequestHandler继承自BaseRequestHandler

(6) 看wsgi内部的第一个 if语句,如果请求头中'Expect'''中间有'100-continue',将'HTTP/1.1 100 Continue\r\n\r\n'写入到wfile中。

- headers is an instance of email.message.Message (or a derived class) containing the header information;
- wfile is a file object open for writing.

(7) 不看中间的函数定义,到了最重要的一行execute(self.server.app),(创建WSGI server时将app作为参数传递并保存在了WSGI server中)这里调用app来处理客户端请求。

(8) WSGI中调用app 会使用到Flask中的__call__方法。

(9) 不看具体处理过程,WSGI server现在完成了接收用户请求,调用flask 应用来处理请求的过程。


然后开始了真正处理一个请求的过程。

(1) 回到Flask类中看__call__方法:
__call__(self, environ, start_response) ,这里的self 是flask应用本身,即实例化的appenviron, start_responseWSGI server 提供。__call__最后会返回wsgi_app(environ, start_response),即使用wsgi_app 来处理客户端的请求。

(2) wsgi_app 中:
ctx = self.request_context(environ)首先将environ 封装在了一个请求上下文变量ctx中。请求上下文使用结构存储数据,ctx.push()environ 压栈放在栈顶。

(3) 关键的一行response = self.full_dispatch_request() 使用 full_dispatch_request() 处理请求,随后返回处理结果:return response(environ, start_response)

(4)full_dispatch_request() :

Dispatches the request and on top of that performs request pre and postprocessing as well as HTTP exception catching and error handling.

首先是self.try_trigger_before_first_request_functions()
__init__函数中设置了self._got_first_request = Falsetry_trigger_before_first_request_functions()的最后一行设置了self._got_first_request = True,表明要开始处理请求了。

不分析太多了,full_dispatch_request() 关键是调用dispatch_request() 做真实处理,最后返回finalize_request() 将处理结果变成真正的响应。

(5) dispatch_request()

Does the request dispatching. Matches the URL and returns the return value of the view or error handler. This does not have to be a response object. In order to convert the return value to aproper response object, call :func: make_response .

req = _request_ctx_stack.top.request 将请求上下文栈顶的请求赋值给req,(req 会包含请求的详细信息)
rule = req.url_rulereq 中的url_rule (’/’)赋值给rule,(请求和flaskapp中代码一致)
③ 在运行@app.route("/") 时将endpoint( ‘/’)和view_func(’index’)的映射关系到了view_functions字典中。
④如果在flaskapp 代码中找不到输入的 URL,会返回 404 错误。
⑤如果输入的URL在flaskapp 代码有相应的 URL,会返回 flaskapp 对应的视图函数。
⑥上面说的是完整的URL-Viewfunc映射关系,flaskapp 以及 WSGI server 中使用的是endpoint(‘/’, ‘/index’, ‘/about’) -Viewfunc 的映射关系。
⑦总结来说,dispatch_request()判断用户输入的URL在flask应用中有没有相关的定义。如果有,将对应的视图函数的内容返回到full_dispatch_request: rv = self.preprocess_request()

(6) full_dispatch_request最后会调用finalize_request(rv) 方法将返回结果转换成一个真正的响应。

(7) finalize_request(rv) 代码不复杂,主要就是使用response = self.make_response(rv) 将处理结果变成一个真正的响应(视图函数中字符串变成html形式),最后return response,这个响应会返回到full_dispatch_request,然后返回到wsgi_app

(8) 以上wsgi_app 完成了一个请求处理的过程,最后return response(environ, start_response) 将处理结果返回给 WSGI serverWSGI server再返回给客户端(浏览器),浏览器中显示了2017-08-21,即flaskapp中index视图函数的返回值。

这里写图片描述


  • 12
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值