Python多线程跨文件全局变量传值始终返回None的解决方案问询
问题根因分析
你遇到的输出始终为None的核心原因有两个:
- 跨模块全局变量作用域隔离:Python中
global关键字声明的变量仅属于当前模块的全局作用域,thread.py里修改的a是thread模块的独立全局变量,和main_thread.py里定义的全局变量a是完全不同的两个对象,因此主程序读到的永远是初始值None。 - 无锁读写共享变量存在线程安全风险:即使修正了作用域问题,多线程场景下直接读写共享变量不做并发控制,也容易读到脏数据。
可行实现方案
方案1:使用queue.Queue传递数据(推荐)
队列是Python多线程间通信的官方推荐实现,天生线程安全,不需要手动加锁,支持数据缓冲,适合持续传递增量数据的场景。
修改后的代码如下:
main_thread.py
import threading import time from queue import Queue from thread import thread_function def main (): # 初始化队列,maxsize设置缓冲区大小,0表示无限制 msg_queue = Queue(maxsize=10) # 将队列作为参数传入子线程函数 thread_1 = threading.Thread(target=thread_function, args=(msg_queue,), daemon=True) thread_1.start() while True: # 读取队列中的值,get()为阻塞读,也可使用get_nowait()实现非阻塞读取 a = msg_queue.get() print(a) time.sleep(2) if __name__ == '__main__': main()
thread.py
import random import time def thread_function(msg_queue): while True: a = random.randint(1,10) # 将生成的值写入队列,put()为阻塞写,满队列时会等待缓冲区空闲 msg_queue.put(a) # 此处模拟实际场景中抓取网站信息的耗时逻辑 time.sleep(0.5)
该方案特点:
- 原生线程安全,不需要自行处理锁逻辑
- 支持缓冲多组历史数据,不会因为主程序读取速度慢导致数据丢失
- 可通过
Queue.task_done()、Queue.join()实现生产消费端的进度同步
方案2:修正后的跨模块共享变量方式
如果你的场景仅需要获取最新状态、不需要保留历史数据,可以通过公共模块承载共享变量,同时加读写锁保证线程安全。
首先新增公共模块common_var.py用于存储共享变量和锁:
import threading # 共享状态变量 a = None # 读写锁 lock = threading.Lock()
调整后的main_thread.py
import threading import time from thread import thread_function import common_var def main (): thread_1 = threading.Thread(target=thread_function, daemon=True) thread_1.start() while True: # 加锁读取共享变量 with common_var.lock: print(common_var.a) time.sleep(2) if __name__ == '__main__': main()
调整后的thread.py
import random import time import common_var def thread_function (): while True: a = random.randint(1,10) # 加锁修改共享变量 with common_var.lock: common_var.a = a time.sleep(0.5)
该方案注意事项:
- 所有读写共享变量的位置都必须加锁,否则会出现竞态条件,导致读到异常值
- 仅能获取变量的最新值,主程序读速慢于子线程生产速度时会丢失中间产生的历史值
内容的提问来源于stack exchange,提问作者Workingsolutions
相关产品推荐
相关产品推荐

