Python-全局变量在flask中是线程安全的吗?如何在请求之间共享数据?
在我的应用中,公共对象的状态通过发出请求来更改,而响应取决于状态。
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查询。
self.param
增加1。 - 在执行return语句之前,线程将切换到客户端2。
self.param
再次递增。 - 线程切换回客户端1,并向客户端返回数字2,例如。
- 现在,该线程移至客户端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的gobject。另一个常见的情况是管理数据库连接的某些顶级对象。这种global
类型的区别在于,它对每个请求都是唯一的,在请求之间不使用,并且有一些东西可以管理资源的建立和拆除。
以上是 Python-全局变量在flask中是线程安全的吗?如何在请求之间共享数据? 的全部内容, 来源链接: utcz.com/qa/433916.html