即使创建了单独的目录,新会话文件也会覆盖旧会话文件(Flask)

New session files overwriting old session files even though a separate directory is created (Flask)

我有一个 Flask 应用程序,我需要将应用程序不同实例的临时文件存储在一个文件夹中,该文件夹的名称是应用程序打开时的时间。 我有一个索引函数如下:

@app.route('/')
def index():
    session["now"] = time.time() * 100.0
    os.mkdir(str(session["now"]))

上面的代码创建了一个目录,目录的名称是应用程序打开的时间。 当我在 Chrome 的两个单独选项卡上打开应用程序时,会按预期生成两个不同的目录。

但是,有一个问题。 我的 UI 中有一个文本区域,其文本需要保存在上面创建的目录中的文本文件中。我使用 POST 请求发送数据。 下面是Flask-Python方法:

@app.route('/rt3/', methods=['POST']) 
def fn3():
    x = request.get_json()
    data = x['textbox1']
    f = open("./" + str(session["now"]) + "/mytext.txt", "w")
    f.write(data)
    f.close()

问题是这样的:无论我在哪个 Chrome 选项卡上单击 "run" 按钮,文本文件总是保存在稍后创建的会话的目录中。因此,同一个文本文件被一次又一次地覆盖。 既然用了session变量,那不应该保存在自己session的目录下吗? 为什么会话变量会被覆盖?

这完全符合预期。当 运行 Flask 在本地时,您很可能使用一个 process/instance 来处理您的所有请求(在较新的 Flask 版本中默认为多线程,因此您可以并行处理多个请求)。

因此请注意,无论您打开多少 Chrome 个选项卡,您都没有应用程序的不同实例,只有一个。您需要使用 gunicorn 或任何其他 WSGI 来生成多个实例并使它们完全独立。

在您的示例中,当您执行 session["now"] = time.time() * 100.0 时,您只需覆盖每次 session["now"] 的内容。因此,当从 fn3() 访问它时,您显然会得到最后一个版本(最后一个覆盖)。

现在,如果你真的想实现这个,你需要在每个请求中传递一个明确的 "directory" 标识符(不一定基于时间),这样你就可以用它来创建目录并写入文件到它。

编辑 (20.02.2020)

经过更多研究,Flask 会话存储在客户端的 cookie 中(参见 doc

因此,当您从来自 2 个不同选项卡(来自同一浏览器 'instance')的 2 个请求调用 session 时,您会访问相同的 cookie,因此访问相同的值。但是,如果您打开另一个浏览器(或新的 Chrome 隐身标签),您将拥有一个新的 cookie,因此您将使用不同的会话值。