You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask多线程场景下全局变量跨模块共享失败问题求助

问题背景

开发Python Flask服务时,希望通过后台线程定期查询后端服务并更新共享数据,让GET请求直接读取该数据以避免每次请求都耗时查询。测试用例中全局变量cnt由后台线程递增,index.html展示其值:

<h1>cnt = {{ cnt }}</h1>
遇到的问题
  • 单模块时功能正常:刷新页面,cnt值随后台线程递增同步更新。
  • 拆分视图到独立routes模块后功能失效:后台线程日志显示cnt持续递增,但页面始终显示cnt = 1,仿佛两个模块有独立的cnt实例。
说明

已查阅相关问题未找到匹配场景;示例代码未添加锁保护和线程终止处理,为简化刻意忽略。

代码示例

单模块(功能正常)

hello.py内容:

from flask import Flask, render_template
import threading as th
from time import sleep

cnt = 0

app = Flask(__name__)

# 后台线程执行逻辑
def do_stuff():
    global cnt
    while True:
        cnt += 1
        print(f'do_stuff: cnt={cnt}')
        sleep(1)

# 启动后台线程
t = th.Thread(target=do_stuff)
t.start()

@app.route("/")
def hello():
    return render_template('index.html', cnt=cnt)

跨模块(功能失效)

主文件hello.py:

from flask import Flask
import threading as th
from time import sleep

cnt = 0

app = Flask(__name__)

# 后台线程执行逻辑
def do_stuff():
    global cnt
    while True:
        cnt += 1
        print(f'do_stuff: cnt={cnt}')
        sleep(1)

# 启动后台线程
t = th.Thread(target=do_stuff)
t.start()

import routes

独立routes.py文件:

# routes.py

from hello import app, cnt 
from flask import render_template

@app.route("/")
def hello():
    return render_template('index.html', cnt=cnt)
问题原因与解决办法

原因

Python中不可变类型的变量导入会创建副本。cnt是整数(不可变类型),routes.py中from hello import cnt会把导入时的cnt值(线程启动后第一次递增到1时完成导入)复制到routes模块的命名空间中,后续后台线程修改hello模块中的cnt时,routes模块里的副本不会同步更新。

解决办法

方法1:用可变类型包装共享数据

把cnt放在可变容器(比如字典、列表)中,这样导入的是容器的引用,修改容器内的元素会同步反映到所有模块。

修改hello.py:

# 用字典包装cnt
shared_data = {'cnt': 0}

def do_stuff():
    global shared_data
    while True:
        shared_data['cnt'] += 1
        print(f'do_stuff: cnt={shared_data["cnt"]}')
        sleep(1)

修改routes.py:

from hello import app, shared_data 

@app.route("/")
def hello():
    return render_template('index.html', cnt=shared_data['cnt'])

方法2:通过模块引用访问变量

在routes.py中不直接导入cnt,而是导入整个hello模块,每次访问都通过模块引用获取最新值:

修改routes.py:

import hello
from flask import render_template

@hello.app.route("/")
def hello_route():
    return render_template('index.html', cnt=hello.cnt)

方法3:使用Flask的g对象或应用上下文(不推荐此场景)

Flask的g对象是请求上下文内的共享空间,但后台线程不属于请求上下文,无法直接使用;若要使用需要手动推送上下文,复杂度较高,不适合这种后台线程持续更新的场景。

内容的提问来源于stack exchange,提问作者joao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 08:10:23