flask学习笔记(三)——理解Context(上下文)和请求钩子

本文介绍了Flask框架中的Context概念,包括Application Context和Request Context,以及它们在程序运行时的作用。同时,详细讲解了请求钩子,如@before_first_request、@before_request、@after_request和@teardown_request,如何在请求生命周期的不同阶段发挥作用。文章还提到,离开请求上下文后无法访问request对象,并解释了Flask如何通过Werkzeug的Local Stack实现线程间上下文隔离。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Context(上下文)

上下文的中文解释:即语境、语意,是语言学科(语言学、社会语言学、篇章分析、语用学、符号学等)的概念。

比如,把一整段文字中某一句话单独来看,可能会让人丈二和尚摸不着头脑,产生不同的理解,但是放在整段文字当中时,你就很容易理解是什么意思,不会产生歧义。反过来,同样的一句话放在不同段落里边,产生的意思也会不一样,而这个段落就可以理解为上下文,也就是上文解释中的语境。

在计算机程序里边,上下文可以理解为程序所运行时的环境,这个环境具体来说可以说是变量和传进来的参数。一般来讲,我们所设计的函数都不是单独的,都会有很多的外部变量,缺乏这些变量,函数就没法运行,只有把这些变量赋值传到函数中,才能正确执行函数,而这些赋值的集合就叫做上下文。

Flask 中的Application Context(程序上下文)和Request Context(请求上下文)

1、Application 就是调用 app = Flask(__name__) 时创建的app对象。

2、Request 指每次http请求发生时,WSGI server 调用Flask.call()之后,在Flask对象内部创建的Request对象

3、application 的生命周期大于request,一个application存活期间,可能发生多次http 请求

from flask import request
@app.route('/')
def index():
    user_agent = reqeust.headers.get('User-Agent')
    return user_agent

理解请求钩子:

@before_first_request :注册一个函数,在处理第一个请求前运行

@before_request :注册一个函数,在每次请求前运行

@after_request :注册一个函数,如果没有未处理的异常抛出,在每次请求后运行

@teardown_request :注册一个函数,即使有未处理的异常抛出,也在每次请求后运行

在每个请求上下文的函数中,我们都可以访问request对象,然而request对象并不是全局变量,离开了请求的生命周期,上下文环境不在了,也就无法获取request对象了,而上面的四中hook函数,会挂载在生命周的不同阶段。

下面这段代码就会抛出RuntimeError:working outside of request context

def handle_request():
    print request.url
handle_request()

可以使用Flask的内部方法request_context()来构建一个请求上下文

from werkzeug.text import EnvironBuilder
ctx = app.request_context(EnvironBuilder('/','http://localhost/').get_environ())
ctx.push()
try:
    print request.url
finally:
    ctx.pop()
对于Flask Web应用来说,每个请求就是一个独立的线程。请求之间的信息要完全隔离,避免冲突,这就需要使用到Thread Local
Thread Local
对象是保存状态的地方,在Python中,一个对象的状态都被保存在对象携带的一个字典中,**Thread Local **则是一种特殊的对象,它的“状态”对线程隔离 —— 也就是说每个线程对一个 Thread Local 对象的修改都不会影响其他线程。这种对象的实现原理也非常简单,只要以线程的 ID 来保存多份状态字典即可,就像按照门牌号隔开的一格一格的信箱。
在Python中获取Thread Local最简单的方式是threading.local()

Flask是一个基于WerkZeug实现的框架,因此Flask的App Context和Request Context是基于WerkZeug的Local Stack的实现。这两种上下文对象类定义在flask.ctx中,ctx.push会将当前的上下文对象压栈压入flask._request_ctx_stack中,这个_request_ctx_stack同样也是个Thread Local对象,也就是在每个线程中都不一样,上下文压入栈后,再次请求的时候都是通过_request_ctx_stack.top在栈的顶端取,所取到的永远是属于自己线程的对象,这样不同线程之间的上下文就做到了隔离。请求结束后,线程退出,ThreadLocal本地变量也随即销毁,然后调用ctx.pop()弹出上下文对象并回收内存。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值