美文网首页
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