笨鸟编程-零基础入门Pyhton教程

 找回密码
 立即注册

请求上下文

发布者: 笨鸟自学网



上下文如何工作

如果你研究 Flask WSGI 应用内部如何工作,你会找到和这非常相似的一段代码:

def wsgi_app(self, environ):
    with self.request_context(environ):
        try:
            response = self.full_dispatch_request()
        except Exception, e:
            response = self.make_response(self.handle_exception(e))
        return response(environ, start_response)

request_context() 方法返回一个新的 RequestContext 对象,并结合 with 声明来绑定上下文。 从相同线程中被调用的一切,直到 with 声明结束前,都可以访问全局的请求 变量( flask.request 和其它)。

请求上下文内部工作如同一个栈。栈顶是当前活动的请求。 push() 把上下文添加到栈顶, pop() 把它移出栈。在出栈时,应用的 teardown_request() 函数也会被执行。

另一件需要注意的事是,请求上下文被压入栈时,并且没有当前应用的应用上下文, 它会自动创建一个 应用上下文 。

回调和错误

在 Flask 中,请求处理时发生一个错误时会发生什么?这个特殊的行为在 0.7 中 变更了,因为我们想要更简单地得知实际发生了什么。新的行为相当简单:

  1. 在每个请求之前,执行 before_request() 上绑定的函数。 如果这些函数中的某个返回了一个响应,其它的函数将不再被调用。任何情况 下,无论如何这个返回值都会替换视图的返回值。
  2. 如果 before_request() 上绑定的函数没有返回一个响应, 常规的请求处理将会生效,匹配的视图函数有机会返回一个响应。
  3. 视图的返回值之后会被转换成一个实际的响应对象,并交给 after_request() 上绑定的函数适当地替换或修改它。
  4. 在请求的最后,会执行 teardown_request() 上绑定的函 数。这总会发生,即使在一个未处理的异常抛出后或是没有请求前处理器执行过 (例如在测试环境中你有时会想不执行请求前回调)。

现在错误时会发生什么?在生产模式中,如果一个异常没有被捕获,将调用 500 internal server 的处理。在生产模式中,即便异常没有被处理过,也会往上冒 泡抛给给 WSGI 服务器。如此,像交互式调试器这样的东西可以提供有用的调试信息。

在 0.7 中做出的一个重大变更是内部服务器错误不再被请求后回调传递处理,而且 请求后回调也不再保证会执行。这使得内部的调度代码更简洁,易于定制和理解。

新的绑定于销毁请求的函数被认为是用于代替那些请求的最后绝对需要发生的事。

销毁回调

销毁回调是是特殊的回调,因为它们在不同的点上执行。严格地说,它们不依赖实际 的请求处理,因为它们限定在 RequestContext 对象的生命周期。 当请求上下文出栈时, teardown_request() 上绑定的函数会 被调用。

这对于了解请求上下文的寿命是否因为在 with 声明中使用测试客户端或在命令行 中使用请求上下文时被延长很重要:

with app.test_client() as client:
    resp = client.get('/foo')
    # the teardown functions are still not called at that point
    # even though the response ended and you have the response
    # object in your hand

# only when the code reaches this point the teardown functions
# are called.  Alternatively the same thing happens if another
# request was triggered from the test client

从这些命令行操作中,很容易看出它的行为:

>>> app = Flask(__name__)
>>> @app.teardown_request
... def teardown_request(exception=None):
...     print 'this runs after request'
...
>>> ctx = app.test_request_context()
>>> ctx.push()
>>> ctx.pop()
this runs after request
>>>

注意销毁回调总是会被执行,即使没有请求前回调执行过,或是异常发生。测试系 统的特定部分也会临时地在不调用请求前处理器的情况下创建请求上下文。确保你 写的请求销毁处理器不会报错。


Archiver|手机版|笨鸟自学网 ( 粤ICP备20019910号 )

GMT+8, 2024-9-8 11:49 , Processed in 0.032203 second(s), 17 queries .

© 2001-2020

返回顶部