当前位置: 首页 > 面试题库 >

全局变量在flask中是线程安全的吗?如何在请求之间共享数据?

曹乐意
2023-03-14
问题内容

在我的应用中,公共对象的状态通过发出请求来更改,而响应取决于状态。

class SomeObj():
    def __init__(self, param):
        self.param = param
    def query(self):
        self.param += 1
        return self.param

global_obj = SomeObj(0)

@app.route('/')
def home():
    flash(global_obj.query())
    render_template('index.html')

如果我在开发服务器上运行此程序,则期望得到1、2、3等。如果同时从100个不同的客户发出请求,会出问题吗?预期结果将是100个不同的客户端各自看到一个从1到100的唯一数字。或者会发生以下情况:

  1. 客户端1查询。self.param增加1。
  2. 在执行return语句之前,线程将切换到客户端2。self.param再次递增。
  3. 线程切换回客户端1,并向客户端返回数字2,例如。
  4. 现在,该线程移至客户端2,并向其返回数字3。
    由于只有两个客户,因此预期结果是1和2,而不是2和3。跳过了一个数字。

当我扩展应用程序时,这实际上会发生吗?我应该考虑什么替代全局变量?


问题答案:

你不能使用全局变量来保存此类数据。它不仅不是线程安全的,而且不是进程安全的,并且生产中的WSGI服务器产生了多个进程。如果你使用线程来处理请求,不仅计数会错误,而且还取决于处理该请求的进程。

使用Flask以外的数据源来保存全局数据。数据库,内存缓存或Redis都是适合的单独存储区域,具体取决于你的需求。如果你需要加载和访问Python数据,请考虑multiprocessing.Manager。你还可以将会话用于每个用户的简单数据。

开发服务器可以在单线程和进程中运行。你将看不到你描述的行为,因为每个请求都将被同步处理。启用线程或进程,你将看到它。app.run(threaded=True)或app.run(processes=10)。(在1.0中,服务器默认为线程化。)

某些WSGI服务器可能支持gevent或其他异步工作器。全局变量仍然不是线程安全的,因为仍然没有针对大多数竞争条件的保护措施。你仍然可以设想这样一个场景:一个工作人员获取了一个值,产生了收益,另一个工作人员对其进行了修改,产生了收益,然后第一个工作人员也对其进行了修改。

如果你在请求期间需要存储一些全局数据,则可以使用Flask的g object。另一个常见的情况是管理数据库连接的某些顶级对象。这种“全局”类型的区别在于,它对每个请求都是唯一的,在请求之间不使用,并且有一些东西可以管理资源的建立和拆除。



 类似资料:
  • 问题内容: 在我的应用中,公共对象的状态通过发出请求来更改,而响应取决于状态。 如果我在开发服务器上运行此程序,则期望得到1、2、3等。如果同时从100个不同的客户发出请求,会出问题吗?预期结果将是100个不同的客户端各自看到一个从1到100的唯一数字。或者会发生以下情况: 客户端1查询。增加1。 在执行return语句之前,线程将切换到客户端2。再次递增。 线程切换回客户端1,并向客户端返回数字

  • 我看到“Dart是一种单线程编程语言”,所以我认为使用全局变量在函数之间传递数据安全吗 我还看到“Dart提供隔离”,并且可以在多核上运行。这意味着如果不同的分离株访问相同的全局变量,这可能是危险的,对吧? 安全吗?如果没有,有什么方法可以在函数之间共享对象,而不将它们作为参数传递呢? 更新: 根据“Florian Loitsch”的回答,我刚刚写了一个关于隔离的全局变量的测试: 您可以看到一个隔

  • 问题内容: 我只想在进程与该进程调用的dll之间共享静态/全局变量。exe和dll在相同的内存地址空间中。我不希望在其他进程之间共享该变量。 问题的阐述: 说是有一个静态/全局变量在。exe 和dll 都具有,因此变量都在两个图像中。 现在,动态加载(或静态)。然后,问题是该变量是否由exe和dll共享。 在Windows中,这两个家伙 永远不会 共享:exe和dll将具有的单独副本。但是,在Li

  • 我手动设置认证cookie为我的登录目的,我想在我的测试中共享认证令牌。第一次我必须在测试中执行登录,然后我必须将授权令牌保存在变量中,并在测试文件中共享它。 下面是一段代码片段,解释我正在尝试做什么以及如何做: 登录est.js: 现在,在测试之后,我有了实际的(非空),如果我必须在所有文件中的所有测试中共享变量,那么我该怎么做?通过这种编码设计,我可以在同一个文件(测试套件)中共享。例如: 我

  • 我有一个Flask应用程序在Gunicorn下运行,使用同步工作进程类型和20个工作进程。该应用程序在启动时读取大量数据,这需要时间和内存。更糟糕的是,每个进程都加载自己的副本,这会导致它花费更长的时间,占用20倍的内存。数据是静态的,不会更改。我想加载一次,让所有20名员工共享。 如果我使用设置,它只加载在一个线程中,并且最初只需要1X内存,但是一旦请求开始进来,它似乎会变成20X。我需要快速随

  • 问题内容: 我知道可以在Python中的各个模块之间共享全局变量。但是,我想知道这种可能性的程度以及原因。例如, global_mod.py mid_access_mod.py bot_modif_mod.py 即使所有模块都共享全局变量x,也将打印“无”。为什么会这样呢?似乎x是在mew()分配给bot_modif_mod.py之前在mid_access_mod.py求值的。 问题答案: 发生这