python 无法在具有文件夹[重复]的线程之间共享全局变量

vlju58qv  于 2023-02-02  发布在  Python
关注(0)|答案(1)|浏览(138)
    • 此问题在此处已有答案**:

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模块、线程或它们之间交互的基本知识,任何帮助都将受到感谢,对于这么长的问题我表示歉意。

2g32fytz

2g32fytz1#

模块之间不共享全局变量
当你说
from moduleA import count您已导入不可变的数字
如果另一个文件中的某些内容更改了模块A中的计数器,它不会更新任何其他内容...它会使用名为count effectively的新变量覆盖您导入的计数器
如果count是一个可变对象,那么任何更改都将反映回来......因此,如果它是一个列表或字典或具有字段的类等。
相反,您可以导入可变的模块
import moduleA
现在,当moduleA更改count时,它正在更改可变模块字段,您可以通过打印moduleA.count在另一个位置看到它

相关问题