首页 > 编程 > Python > 正文

浅谈flask源码之请求过程

2020-02-15 22:32:27
字体:
来源:转载
供稿:网友

Flask

Flask是什么?

Flask是一个使用 Python 编写的轻量级 Web 应用框架, 让我们可以使用Python语言快速搭建Web服务, Flask也被称为 "microframework" ,因为它使用简单的核心, 用 extension 增加其他功能

为什么选择Flask?

我们先来看看python现在比较流行的web框架

Flask Django Tornado Sanic

Flask: 轻, 组件间松耦合, 自由、灵活,可扩展性强,第三方库的选择面广的同时也增加了组件间兼容问题

Django: Django相当于一个全家桶, 几乎包括了所有web开发用到的模块(session管理、CSRF防伪造请求、Form表单处理、ORM数据库对象化、模板语言), 但是相对应的会造成一个紧耦合的情况, 对第三方插件不太友好

Tornado: 底层通过eventloop来实现异步处理请求, 处理效率高, 学习难度大, 处理稍有不慎很容易阻塞主进程导致不能正常提供服务, 新版本也支持asyncio

Sanic: 一个类Flask框架, 但是底层使用uvloop进行异步处理, 可以使用同步的方式编写异步代码, 而且运行效率十分高效.

WSGI

先来看看维基百科对WSGI的定义

Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口.

何为网关, 即从客户端发出的每个请求(数据包)第一个到达的地方, 然后再根据路由进行转发处理. 而对于服务端发送过来的消息, 总是先通过网关层, 然后再转发至客户端

那么可想而知, WSGI其实是作为一个网关接口, 来接受Server传递过来的信息, 然后通过这个接口调用后台app里的view function进行响应.

先看一段有趣的对话:

Nginx:Hey, WSGI, 我刚收到了一个请求,我需要你作些准备, 然后由Flask来处理这个请求.
WSGI:OK, Nginx. 我会设置好环境变量, 然后将这个请求传递给Flask处理.
Flask:Thanks. WSGI给我一些时间,我将会把请求的响应返回给你.
WSGI:Alright, 那我等你.
Flask:Okay, 我完成了, 这里是请求的响应结果, 请求把结果传递给Nginx.
WSGI:Good job! Nginx, 这里是响应结果, 已经按照要求给你传递回来了.
Nginx:Cool, 我收到了, 我把响应结果返回给客户端.大家合作愉快~

对话里面可以清晰了解到WSGI、nginx、Flask三者的关系

下面来看看Flask中的wsgi接口(注意:每个进入Flask的请求都会调用Flask.__call__)

# 摘自Flask源码 app.pyclass Flask(_PackageBoundObject):  # 中间省略  def __call__(self, environ, start_response):    return self.wsgi_app(environ, start_response)        def wsgi_app(self, environ, start_response):    # environ: 一个包含全部HTTP请求信息的字典, 由WSGI Server解包HTTP请求生成    # start_response: WSGI Server提供的函数, 调用可以发送响应的状态码和HTTP报文头,    # 函数在返回前必须调用一次.    :param environ: A WSGI environment.    :param start_response: A callable accepting a status code,      a list of headers, and an optional exception context to      start the response.    # 创建上下文    ctx = self.request_context(environ)    error = None    try:      try:        # 把上下文压栈        ctx.push()        # 分发请求        response = self.full_dispatch_request()      except Exception as e:        error = e        response = self.handle_exception(e)      except:        error = sys.exc_info()[1]        raise      # 返回结果      return response(environ, start_response)    finally:      if self.should_ignore_error(error):        error = None        # 上下文出栈        ctx.auto_pop(error)            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表