美文网首页
Flask源码之一个请求的旅程(二)

Flask源码之一个请求的旅程(二)

作者: 看五年前自己的文章真是唏嘘不已 | 来源:发表于2021-05-02 22:41 被阅读0次

入口

由上一篇文章我们知道 Flask 要有如下函数或者一个实现了 __call__方法的类,才可以被wsgi server调用

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, web!</h1>']
class Applications(object):
    def __call__(self,environ, start_response)
        start_response('200 OK', [('Content-Type', 'text/html')])
        return [b'<h1>Hello, web!</h1>']
# 实现了__call__方法的类就可以像函数一样被调用
# 例如 application=Applications()
# application(environt,start_response)

Flask是怎么做的呢? 我们来看一下简单的 Flask demo

from flask import Flask

flask_app = Flask(__name__)


@flask_app.route('/')
def hello_world():
    return "hello flask"


# python3 my_wsgi_server.py flask_app:flask_app
if __name__ == '__main__':
    flask_app.run()

这段代码很简单,先是创建了一个Flask实例(对象),然后调用Flask对象的route方法。

启动项目的时候调用Flask对象的run()方法

我们先不去看run方法内部是如何实现的,因为Flask内置了一个wsgi server,从 run方法进入会涉及到很多 wsgi server 的代码,而生产环境我们一般不用这个 wsgi server,而是用gunicorn或者uwsgi

pycharm中按 ctrl,鼠标左键点击 Flask查看源码

我们可以看到Flask是一个类,那么他一定实现 __call__方法

Flask源码

点击 pycharm左侧的 structure我们可以看到果然有 __call__方法,而且这个 __call__方法的参数是 environ,start_responsewsgi server最后调用的也是这个方法

image-20201224152301791

我们进入到这个方法,随便打个断点

启动项目

接下来我们以 debug的方式启动项目

image-20201224152851475

浏览器访问 http://127.0.0.1:5000/,我们看到 pycharm在 我们的断点处停了下来,__call__方法又调用了wsgi_app方法,参数都一摸一样

image-20201224153123774

再看 wsgi_app方法

    def wsgi_app(self, environ, start_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:  # noqa: B001
                error = sys.exc_info()[1]
                raise

            return response(environ, start_response)
        finally:
            if self.should_ignore_error(error):
                error = None
            ctx.auto_pop(error)

这个方法其实就做了以下几件事

  1. 路由:就是根据你的请求,找到对应的视图函数。例如我们的请求 http://127.0.0.1:5000/ 会被 @flask_app.route('/')匹配到,那么就会调用 hello_world方法
  2. 处理请求上下文和应用上下文
  3. 错误处理
  4. 回调 wsgi server提供的 start_response 方法把结果返回给 wsgi server

接下来分别介绍这几个部分

相关文章

网友评论

      本文标题:Flask源码之一个请求的旅程(二)

      本文链接:https://www.haomeiwen.com/subject/oouxdltx.html