Python Flask 的 session 是全局的,如何避免变量传值重复或被覆盖?

比如: session['yonghuming'] = request.form['username']

把表单中的 username 传给 session ,用 yonghuming 变量保存,下次可以用 session.get('yonghuming')把这个值取出来。

如果 session 是全局的话,再一些特殊情况下(比如,定时任务、异步认为中,前面存的 yonghuming 还没来得及读取,就被后面同样的 request.form['username']赋值给覆盖了。这怎么整?

另外,说 Flask 的 session 设计是 cookie based ,按理说,应该是每个用户的请求又应该算是非全局的,可以重名,不用担心被覆盖吧?


Python Flask 的 session 是全局的,如何避免变量传值重复或被覆盖?

12 回复

对于 session 变量本身,它是个 threading-local 变量,所以不会有多线程问题。

而且 Python 除了 PyPy 开不了多线程,整个 Python 进程就是个巨大的单线程程序。


Flask的session是基于cookie的客户端session,每个用户独立,但如果你指的是全局变量或模块级变量被多个请求共享导致的问题,那确实需要注意。

Flask应用在多线程/多worker环境下运行时,全局变量会被所有请求共享。比如你在模块层面定义了一个列表,所有用户请求都可能修改它,这肯定会导致数据混乱。

解决方案:

  1. 使用Flask的g对象:针对单个请求的生命周期存储数据,请求结束后自动清理。

    from flask import g, request
    [@app](/user/app).before_request
    def set_user():
        g.user_id = request.args.get('user_id')
    
  2. 使用请求上下文:通过request对象传递数据,每个请求都有独立的request对象。

  3. 彻底避免模块级可变全局变量:如果必须用全局状态,考虑使用线程安全的存储,比如:

    from threading import Lock
    user_data = {}
    data_lock = Lock()
    
    def update_user_data(user_id, data):
        with data_lock:
            user_data[user_id] = data
    
  4. 使用数据库或Redis:持久化存储用户数据,这是最可靠的方式。

关键点:Flask的session本身是用户隔离的,问题通常出在你自己定义的全局变量上。确保请求相关的数据要么放在g/request里,要么用用户ID作为键存储在字典中。

总结:用g对象或请求上下文替代全局变量。

flask 中的 request 、 session 、 g 都是协程 /进程安全的。简单说,它们看似是全局变量,但其实每个请求的值都是单独保存的,不会相互影响。

如果想明白内部的实现,可以看这篇文章: http://cizixs.com/2017/01/13/flask-insight-context

另,迷之 yonghuming 变量。

谢谢,按这个解释思路,如果 session[‘yonghuming’] = request.form[‘username’] 的’yonghuming’在 10 分钟之后取,但是中途在第 3 分钟的时候,被另外一个 form 又赋值了一次,那 10 分钟之后取的‘ yonghuming ’,其实是第 3 分钟复制的那个啦?

是为了区分说清楚两个 username 呐,要体现出会用两种语言来命名的优势来~

我觉得你对 Flask 的 session 有个误解。 Flask 的 session 是 cookie based ,所以每次请求都是从 cookie 里面抽出来的值,不存在服务器上。至于 cookie 是怎么维持的呢?

比如你某次请求让 flask 设置了一个 cookie ,服务器在送给客户端的 HTTP Header 里面会有一句

Set-Cookie: name=value …(省略一些 cookie 的元信息)

然后下次浏览器发送给服务器的 HTTP Header 会带上:

Cookie: name=value

也就是说这来回传输的 HTTP 头维持了状态。

回到你的问题,每次 flask 处理某个请求, session 对象都是临时从 HTTP Header 里面重建出来的。 10 分钟之后是什么,这要看浏览器给你的是什么。

定时任务还有 request ?

这就是 Flask 最具特色、魅力和争议的黑魔法了。它的 request, session 不是一个普通对象。是一个逗比对象。

谢谢,明白~ 需要换个方式处理这个数值了。

你说的对,想到后来不会再有 request 了,值都取不到。

Flask 的 session 是 ThreadLocal 的,每个用户都有一个自己的栈,所以数据不会混乱的

那你咋不对 request 的正确性进行怀疑呢??

骚年,深入了解下 flask 内部实现吧。 兼具了争议和赞美的一种表示方法

你可能混淆了 session 域和 application 域

回到顶部