Flask-app.py(4)

def do_teardown_request(

        self,

        exc: BaseException | None = _sentinel,  # type: ignore[assignment]

    ) -> None:

        """Called after the request is dispatched and the response is

        returned, right before the request context is popped.

        This calls all functions decorated with

        :meth:`teardown_request`, and :meth:`Blueprint.teardown_request`

        if a blueprint handled the request. Finally, the

        :data:`request_tearing_down` signal is sent.

        This is called by

        :meth:`RequestContext.pop() <flask.ctx.RequestContext.pop>`,

        which may be delayed during testing to maintain access to

        resources.

        :param exc: An unhandled exception raised while dispatching the

            request. Detected from the current exception information if

            not passed. Passed to each teardown function.

        .. versionchanged:: 0.9

            Added the ``exc`` argument.

        """

        if exc is _sentinel:

            exc = sys.exc_info()[1]

        for name in chain(request.blueprints, (None,)):

            if name in self.teardown_request_funcs:

                for func in reversed(self.teardown_request_funcs[name]):

                    self.ensure_sync(func)(exc)

        request_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc)

这段代码是 Flask 框架中的一个方法,该方法名为 do_teardown_request。它是在请求处理完成、响应返回之后,请求上下文被弹出之前调用的。

如果传递了 exc 参数,则将其赋给传递的异常,否则从当前的异常信息中获取。然后,方法遍历了请求上下文中涉及的蓝图(Blueprints),并按照逆序执行与请求拆除相关的函数。最后,发送了 request_tearing_down 信号,其中包括 exc 参数。

这段代码的作用是在请求处理的最后阶段执行用于清理资源或处理异常的函数,并发送相应的信号通知其他相关模块。

同时,这段代码展示了在 Flask 框架中如何进行资源清理和异常处理的一般实现方式。

def do_teardown_appcontext(

        self,

        exc: BaseException | None = _sentinel,  # type: ignore[assignment]

    ) -> None:

        """Called right before the application context is popped.

        When handling a request, the application context is popped

        after the request context. See :meth:`do_teardown_request`.

        This calls all functions decorated with

        :meth:`teardown_appcontext`. Then the

        :data:`appcontext_tearing_down` signal is sent.

        This is called by

        :meth:`AppContext.pop() <flask.ctx.AppContext.pop>`.

        .. versionadded:: 0.9

        """

        if exc is _sentinel:

            exc = sys.exc_info()[1]

        for func in reversed(self.teardown_appcontext_funcs):

            self.ensure_sync(func)(exc)

        appcontext_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc)

这段代码是Flask应用程序在弹出应用程序上下文之前调用的方法。在处理请求时,应用程序上下文会在请求上下文之后弹出。

在该方法中:

  • 如果没有传入异常(exc),则会使用sys.exc_info()[1]获取异常。
  • 然后,会调用所有装饰有teardown_appcontext的函数。
  • 最后,会发送appcontext_tearing_down信号。

这段代码的主要功能是在应用程序上下文被弹出之前执行必要的清理操作,包括调用已装饰的teardown_appcontext函数和发送appcontext_tearing_down信号。

def app_context(self) -> AppContext:

        """Create an :class:`~flask.ctx.AppContext`. Use as a ``with``

        block to push the context, which will make :data:`current_app`

        point at this application.

        An application context is automatically pushed by

        :meth:`RequestContext.push() <flask.ctx.RequestContext.push>`

        when handling a request, and when running a CLI command. Use

        this to manually create a context outside of these situations.

        ::

            with app.app_context():

                init_db()

        See :doc:`/appcontext`.

        .. versionadded:: 0.9

        """

        return AppContext(self)

    def request_context(self, environ: WSGIEnvironment) -> RequestContext:

        """Create a :class:`~flask.ctx.RequestContext` representing a

        WSGI environment. Use a ``with`` block to push the context,

        which will make :data:`request` point at this request.

        See :doc:`/reqcontext`.

        Typically you should not call this from your own code. A request

        context is automatically pushed by the :meth:`wsgi_app` when

        handling a request. Use :meth:`test_request_context` to create

        an environment and context instead of this method.

        :param environ: a WSGI environment

        """

        return RequestContext(self, environ)

这段代码定义了两个方法:app_contextrequest_context。这两个方法用于创建应用程序上下文(AppContext)和请求上下文(RequestContext)。

app_context方法返回一个应用程序上下文对象,可以使用with语句将上下文推送到当前应用程序,从而使current_app指向这个应用程序。应用程序上下文会在处理请求时和运行CLI命令时自动推送,也可以在这些情况之外手动创建上下文。

request_context方法接受一个WSGI环境作为参数,并返回一个代表该环境的请求上下文对象。与app_context类似,可以使用with语句将请求上下文推送到当前应用程序,从而使request指向该请求。一般情况下,不需要直接调用这个方法,因为请求上下文会在处理请求时由wsgi_app自动推送,可以使用test_request_context方法来创建环境和上下文。

def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> RequestContext:

        """Create a :class:`~flask.ctx.RequestContext` for a WSGI

        environment created from the given values. This is mostly useful

        during testing, where you may want to run a function that uses

        request data without dispatching a full request.

        See :doc:`/reqcontext`.

        Use a ``with`` block to push the context, which will make

        :data:`request` point at the request for the created

        environment. ::

            with app.test_request_context(...):

                generate_report()

        When using the shell, it may be easier to push and pop the

        context manually to avoid indentation. ::

            ctx = app.test_request_context(...)

            ctx.push()

            ...

            ctx.pop()

        Takes the same arguments as Werkzeug's

        :class:`~werkzeug.test.EnvironBuilder`, with some defaults from

        the application. See the linked Werkzeug docs for most of the

        available arguments. Flask-specific behavior is listed here.

        :param path: URL path being requested.

        :param base_url: Base URL where the app is being served, which

            ``path`` is relative to. If not given, built from

            :data:`PREFERRED_URL_SCHEME`, ``subdomain``,

            :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`.

        :param subdomain: Subdomain name to append to

            :data:`SERVER_NAME`.

        :param url_scheme: Scheme to use instead of

            :data:`PREFERRED_URL_SCHEME`.

        :param data: The request body, either as a string or a dict of

            form keys and values.

        :param json: If given, this is serialized as JSON and passed as

            ``data``. Also defaults ``content_type`` to

            ``application/json``.

        :param args: other positional arguments passed to

            :class:`~werkzeug.test.EnvironBuilder`.

        :param kwargs: other keyword arguments passed to

            :class:`~werkzeug.test.EnvironBuilder`.

        """

        from .testing import EnvironBuilder

        builder = EnvironBuilder(self, *args, **kwargs)

        try:

            return self.request_context(builder.get_environ())

        finally:

            builder.close()

这段代码定义了一个名为test_request_context的方法。它允许从给定值创建的WSGI环境创建一个flask.ctx.RequestContext。这在测试过程中非常有用,可以运行使用请求数据而不需要派发完整请求的函数。通过使用with语句推送上下文,可以使request指向为创建的环境的请求。该方法采用与Werkzeug的werkzeug.test.EnvironBuilder相同的参数,并在应用程序中具有一些默认值。在flask.ctx.RequestContext上下文中返回环境构建器的结果。并在完成后关闭环境构建器。主要功能是为了方便在测试中创建一个包含请求数据的环境,以便在不派发完整请求的情况下运行函数。通过这种方式,您可以模拟请求上下文并进行测试,而无需实际发送HTTP请求。

def wsgi_app(

        self, environ: WSGIEnvironment, start_response: StartResponse

    ) -> cabc.Iterable[bytes]:

        """The actual WSGI application. This is not implemented in

        :meth:`__call__` so that middlewares can be applied without

        losing a reference to the app object. Instead of doing this::

            app = MyMiddleware(app)

        It's a better idea to do this instead::

            app.wsgi_app = MyMiddleware(app.wsgi_app)

        Then you still have the original application object around and

        can continue to call methods on it.

        .. versionchanged:: 0.7

            Teardown events for the request and app contexts are called

            even if an unhandled error occurs. Other events may not be

            called depending on when an error occurs during dispatch.

            See :ref:`callbacks-and-errors`.

        :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: BaseException | None = 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 "werkzeug.debug.preserve_context" in environ:

                environ["werkzeug.debug.preserve_context"](_cv_app.get())

                environ["werkzeug.debug.preserve_context"](_cv_request.get())

            if error is not None and self.should_ignore_error(error):

                error = None

            ctx.pop(error)

    def __call__(

        self, environ: WSGIEnvironment, start_response: StartResponse

    ) -> cabc.Iterable[bytes]:

        """The WSGI server calls the Flask application object as the

        WSGI application. This calls :meth:`wsgi_app`, which can be

        wrapped to apply middleware.

        """

        return self.wsgi_app(environ, start_response)

这段代码定义了wsgi_app方法和__call__方法,用于处理WSGI(Web Server Gateway Interface)请求。在WSGI应用中,__call__方法被WSGI服务器调用,然后调用wsgi_app方法来处理请求。以下是主要功能:

  1. wsgi_app方法负责处理WSGI请求:

    • 通过request_context方法创建请求上下文。
    • 尝试调用full_dispatch_request方法处理请求。如果发生异常,则调用handle_exception方法处理异常。
    • 最终返回响应。
    • 在处理完成后,检查是否需要忽略错误并弹出请求上下文。
  2. __call__方法作为WSGI应用的入口点,被WSGI服务器调用,然后委派给wsgi_app方法来处理请求。

这段代码实现了Flask应用的WSGI处理逻辑,负责处理请求和响应,并在必要时调用异常处理逻辑。

  • 19
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值