• Flask启动原理,源码流程分析


    1.执行Flask的实例对象.run()方法

    from flask import Flask,request,session
    
    app = Flask(__name__)
    
    
    app.secret_key ='sdfsdfsdf'
    
    
    if __name__ == '__main__':
        app.__call__
        app.run()


    2.经过对IP与端口的处理,然后执行 from werkzeug.serving import run_simple中的 run_simple(host, port, self, **options)方法

        def run(self, host=None, port=None, debug=None, **options):
           
            from werkzeug.serving import run_simple
            #查看是否有ip
            if host is None:
                host = '127.0.0.1'
            if port is None:
                # 读取settings文件
                server_name = self.config['SERVER_NAME']
                # print(server_name)#127.0.0.1:80
                if server_name and ':' in server_name:
                    port = int(server_name.rsplit(':', 1)[1])
                    # print(port)#80
                else:
                    port = 5000
            if debug is not None:
                self.debug = bool(debug)
                print(self.debug)
            options.setdefault('use_reloader', self.debug)
            options.setdefault('use_debugger', self.debug)
            try:
                run_simple(host, port, self, **options)
            finally:
                # reset the first request information if the development server
                # reset normally.  This makes it possible to restart the server
                # without reloader and that stuff from an interactive shell.
                self._got_first_request = False
    def run_simple(hostname, port, application, use_reloader=False,
                   use_debugger=False, use_evalex=True,
                   extra_files=None, reloader_interval=1,
                   reloader_type='auto', threaded=False,
                   processes=1, request_handler=None, static_files=None,
                   passthrough_errors=False, ssl_context=None):
        """Start a WSGI application. Optional features include a reloader,
        multithreading and fork support.
    
        This function has a command-line interface too::
    
            python -m werkzeug.serving --help
    
        .. versionadded:: 0.5
           `static_files` was added to simplify serving of static files as well
           as `passthrough_errors`.
    
        .. versionadded:: 0.6
           support for SSL was added.
    
        .. versionadded:: 0.8
           Added support for automatically loading a SSL context from certificate
           file and private key.
    
        .. versionadded:: 0.9
           Added command-line interface.
    
        .. versionadded:: 0.10
           Improved the reloader and added support for changing the backend
           through the `reloader_type` parameter.  See :ref:`reloader`
           for more information.
    
        :param hostname: The host for the application.  eg: ``'localhost'``
        :param port: The port for the server.  eg: ``8080``
        :param application: the WSGI application to execute
        :param use_reloader: should the server automatically restart the python
                             process if modules were changed?
        :param use_debugger: should the werkzeug debugging system be used?
        :param use_evalex: should the exception evaluation feature be enabled?
        :param extra_files: a list of files the reloader should watch
                            additionally to the modules.  For example configuration
                            files.
        :param reloader_interval: the interval for the reloader in seconds.
        :param reloader_type: the type of reloader to use.  The default is
                              auto detection.  Valid values are ``'stat'`` and
                              ``'watchdog'``. See :ref:`reloader` for more
                              information.
        :param threaded: should the process handle each request in a separate
                         thread?
        :param processes: if greater than 1 then handle each request in a new process
                          up to this maximum number of concurrent processes.
        :param request_handler: optional parameter that can be used to replace
                                the default one.  You can use this to replace it
                                with a different
                                :class:`~BaseHTTPServer.BaseHTTPRequestHandler`
                                subclass.
        :param static_files: a list or dict of paths for static files.  This works
                             exactly like :class:`SharedDataMiddleware`, it's actually
                             just wrapping the application in that middleware before
                             serving.
        :param passthrough_errors: set this to `True` to disable the error catching.
                                   This means that the server will die on errors but
                                   it can be useful to hook debuggers in (pdb etc.)
        :param ssl_context: an SSL context for the connection. Either an
                            :class:`ssl.SSLContext`, a tuple in the form
                            ``(cert_file, pkey_file)``, the string ``'adhoc'`` if
                            the server should automatically create one, or ``None``
                            to disable SSL (which is the default).
        """


    3.execute(app) 中 application_iter = app(environ, start_response)即call方法

            def execute(app):
                application_iter = app(environ, start_response)
                try:
                    for data in application_iter:
                        write(data)
                    if not headers_sent:
                        write(b'')
                finally:
                    if hasattr(application_iter, 'close'):
                        application_iter.close()
                    application_iter = None


    4.call方法中返回 return self.wsgi_app(environ, start_response)

    def __call__(self, environ, start_response):
    """Shortcut for :attr:`wsgi_app`."""
    print(environ,start_response)

    return self.wsgi_app(environ, start_response)


    5.首先,处理的是request和session,将请求添加到Local中,即 ctx = self.request_context(environ)

        def wsgi_app(self, environ, start_response):
            
            #处理request,将请求添加到local中
            ctx = self.request_context(environ)
            # 处理request和session
            ctx.push()
            error = None
            try:
                try:
                    # 执行视图函数
                    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)


    5.1.返回的是 return RequestContext(self, environ) 即类的一个实例

        def request_context(self, environ):
            
            return RequestContext(self, environ)


    5.2.执行 ctx.push()方法 保存

        def push(self):
            """Binds the request context to the current context."""
            
            top = _request_ctx_stack.top
            if top is not None and top.preserved:
                top.pop(top._preserved_exc)
    
            # Before we push the request context we have to ensure that there
            # is an application context.
            app_ctx = _app_ctx_stack.top
            if app_ctx is None or app_ctx.app != self.app:
                app_ctx = self.app.app_context()
                app_ctx.push()
                self._implicit_app_ctx_stack.append(app_ctx)
            else:
                self._implicit_app_ctx_stack.append(None)
    
            if hasattr(sys, 'exc_clear'):
                sys.exc_clear()
    
            _request_ctx_stack.push(self)
    
           
            self.session = self.app.open_session(self.request)
            if self.session is None:
                self.session = self.app.make_null_session()


    6.执行视图函数 response = self.full_dispatch_request()方法

        def full_dispatch_request(self):
            """Dispatches the request and on top of that performs request
            pre and postprocessing as well as HTTP exception catching and
            error handling.
    
            .. versionadded:: 0.7
            """
            self.try_trigger_before_first_request_functions()
            try:
                request_started.send(self)
                rv = self.preprocess_request()
                if rv is None:
                    rv = self.dispatch_request()
            except Exception as e:
                rv = self.handle_user_exception(e)
            return self.finalize_request(rv)


    6.1:执行 self.try_trigger_before_first_request_functions()即装饰器@before_first_request装饰所有函数
    6.2:执行 rv = self.preprocess_request()方法 即@before_request装饰所有函数
    6.3:return self.finalize_request(rv)方法 即@after_request装饰所有函数
    response = self.process_response(response)方法
    # 执行after_request 装饰所有的函数 response = handler(response)
    最后处理session self.save_session(ctx.session, response)

    7.return response(environ, start_response) 将处理完的内容返回给用户浏览器

  • 相关阅读:
    Filebeat 日志收集器 安装和配置
    纠错式教学法对比鼓励式教学法 -----Lily、贝乐、英孚,乐加乐、剑桥国际、优学汇、北外青少
    硅谷夜谈
    指路Reactive Programming
    Spring WebFlux 要革了谁的命?
    flink部署操作-flink standalone集群安装部署
    Flink的高可用集群环境
    当怪物来敲门 经典台词
    浅析几种线程安全模型
    最详细的排序解析,理解七大排序
  • 原文地址:https://www.cnblogs.com/ldq1996/p/8244552.html
Copyright © 2020-2023  润新知