- 此问题在此处已有答案**:
Are global variables thread-safe in Flask? How do I share data between requests?(4个答案)
11小时前关门了。
背景
我正在尝试写一个python flask服务器来应答一个简单的请求。在响应中返回的数据是从一个后端服务查询的。由于这个查询可能需要一些时间来完成,我不想同步地做它,我想让它在后台线程中周期性地运行。在这里我可以显式地控制频率。它应该更新一些与flask视图函数共享的数据结构,这样GET请求就可以从共享数据中得到答案。
下面是两个示例代码,在这两个代码中,cnt
都是一个全局变量,从0开始,在一个单独的线程中递增,index.html
文件显示cnt
的值:
<h1>cnt = {{ cnt }}</h1>
我面临的问题
当view函数位于同一模块内时,它的工作方式为:每次使用F5刷新页面时,cnt
的值都会发生变化,我可以看到它在增加。
但是当我把视图函数放在一个单独的routes
模块中(我在hello.py
文件的末尾导入它)时,它就不再工作了:我可以在服务器跟踪中看到后台线程正在增加cnt
,但是当我刷新页面时,我总是看到
cnt = 1
这就好像我现在有了cnt
变量的两个不同副本,即使该变量已经导入到routes
模块中。
备注
我发现了无数关于SO的问题,但没有一个真正解决了这个问题。另外,我非常清楚,在我下面的例子中,没有 * lock * 保护共享数据(这是一个简单的cnt
变量),我也没有处理 * thread termination *。为了保持样本代码最少,现在故意忽略了这一点。
这是密码。
单个模块,工作正常
下面是hello.py
主文件,所有内容都在同一个模块中:
from flask import Flask, render_template
import threading as th
from time import sleep
cnt = 0
app = Flask(__name__)
# Run in background thread
def do_stuff():
global cnt
while True:
cnt += 1
print(f'do_stuff: cnt={cnt}')
sleep(1)
# Create the separate thread
t = th.Thread(target=do_stuff)
t.start()
@app.route("/")
def hello():
return render_template('index.html', cnt=cnt)
正如预期的那样,变量确实在后台线程和视图函数之间共享。
分离模块,不再工作
下面是hello.py
的主要模块,不带view函数:
from flask import Flask
import threading as th
from time import sleep
cnt = 0
app = Flask(__name__)
# Run in background thread
def do_stuff():
global cnt
while True:
cnt += 1
print(f'do_stuff: cnt={cnt}')
sleep(1)
# Create the separate thread
t = th.Thread(target=do_stuff)
t.start()
import routes
下面是单独的routes.py
文件(参见上面hello.py
末尾的导入):
# routes.py
from hello import app, cnt
from flask import render_template
@app.route("/")
def hello():
return render_template('index.html', cnt=cnt)
使用这段代码,网页总是显示cnt = 1
,就好像两个模块有cnt
变量的两个不同示例一样。
我觉得我错过了一些关于python模块、线程或它们之间交互的基本知识,任何帮助都将受到感谢,对于这么长的问题我表示歉意。
1条答案
按热度按时间2g32fytz1#
模块之间不共享全局变量
当你说
from moduleA import count
您已导入不可变的数字如果另一个文件中的某些内容更改了模块A中的计数器,它不会更新任何其他内容...它会使用名为count effectively的新变量覆盖您导入的计数器
如果count是一个可变对象,那么任何更改都将反映回来......因此,如果它是一个列表或字典或具有字段的类等。
相反,您可以导入可变的模块
import moduleA
现在,当moduleA更改count时,它正在更改可变模块字段,您可以通过打印
moduleA.count
在另一个位置看到它