zoukankan      html  css  js  c++  java
  • 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) 将处理完的内容返回给用户浏览器

  • 相关阅读:
    【已解决】github中git push origin master出错:error: failed to push some refs to
    好记心不如烂笔头,ssh登录 The authenticity of host 192.168.0.xxx can't be established. 的问题
    THINKPHP 5.0目录结构
    thinkphp5.0入口文件
    thinkphp5.0 生命周期
    thinkphp5.0 架构
    Django template
    Django queryset
    Django model
    Python unittest
  • 原文地址:https://www.cnblogs.com/ldq1996/p/8244552.html
Copyright © 2011-2022 走看看