全局变量在flask中是线程安全的吗?如何在请求之间共享数据? [英] Are global variables thread safe in flask? How do I share data between requests?

查看:458
本文介绍了全局变量在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. 客户端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的

In my app the state of a common object is changed by making requests, and the response depends on the state.

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')

If I run this on my development server, I expect to get 1, 2, 3 and so on. If requests are made from 100 different clients simultaneously, can something go wrong? The expected result would be that the 100 different clients each see a unique number from 1 to 100. Or will something like this happen:

  1. Client 1 queries. self.param is incremented by 1.
  2. Before the return statement can be executed, the thread switches over to client 2. self.param is incremented again.
  3. The thread switches back to client 1, and the client is returned the number 2, say.
  4. Now the thread moves to client 2 and returns him/her the number 3.

Since there were only two clients, the expected results were 1 and 2, not 2 and 3. A number was skipped.

Will this actually happen as I scale up my application? What alternatives to a global variable should I look at?

解决方案

You can't use global variables to hold this sort of data. Not only is it not thread safe, it's not process safe, and WSGI servers in production spawn multiple processes. Not only would your counts be wrong if you were using threads to handle requests, they would also vary depending on which process handled the request.

Use a data source outside of Flask to hold global data. A database, memcached, or redis are all appropriate separate storage areas, depending on your needs. If you need to load and access Python data, consider multiprocessing.Manager. You could also use the session for simple data that is per-user.


The development server may run in single thread and process. You won't see the behavior you describe since each request will be handled synchronously. Enable threads or processes and you will see it. app.run(threaded=True) or app.run(processes=10). (In 1.0 the server is threaded by default.)


Some WSGI servers may support gevent or another async worker. Global variables are still not thread safe because there's still no protection against most race conditions. You can still have a scenario where one worker gets a value, yields, another modifies it, yields, then the first worker also modifies it.


If you need to store some global data during a request, you may use Flask's g object. Another common case is some top-level object that manages database connections. The distinction for this type of "global" is that it's unique to each request, not used between requests, and there's something managing the set up and teardown of the resource.

这篇关于全局变量在flask中是线程安全的吗?如何在请求之间共享数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆