Python线程中无法从Queue获取消息的问题排查
问题分析与解决方案
核心问题
你的代码无法从队列获取值,主要原因有两个:
- Python版本API错误:Python3中
Thread类的存活状态判断方法是is_alive(),而非Python2时期的isAlive()。原代码中print(f'Thread is {self.isAlive()}')会触发AttributeError,导致线程启动后直接崩溃,根本执行不到后续的队列取值逻辑。 - 队列选型不当:线程间通信应使用线程安全的
queue.Queue,multiprocessing.Queue是为进程间通信设计的,虽然线程也能使用,但没必要,且可能引入不必要的复杂度。
修正后的代码
TemperatureSensorThread.py
from threading import Thread from src.sensor import PowerSetting, TemperatureSensor import queue # 使用线程安全的queue模块 class TemperatureSensorThread(Thread): def __init__(self, q: queue.Queue): super().__init__() self.sensor = TemperatureSensor('temperature_sensor') self.q = q self.last_temp = -1 self.last_pow_setting = PowerSetting.POWER_OFF def run(self) -> None: should_continue = True while should_continue: print(f'Thread is {self.is_alive()}') # 修正为is_alive() try: # 可选:添加超时,避免线程无限阻塞 message: dict = self.q.get(timeout=1) except queue.Empty: continue print(f'Queue message\t{message}') _action = message.get('action') _temp = message.get('temp') sensor_temp = self.last_temp pow_setting = self.last_pow_setting if _action == 'exit': should_continue = False break if _temp is not None: sensor_temp = _temp if _action == 'start': pow_setting = PowerSetting.POWER_ON elif _action == 'stop': pow_setting = PowerSetting.POWER_OFF self.sensor.set_temperature(sensor_temp) self.sensor.turn_on_off(power_setting=pow_setting) self.last_pow_setting = pow_setting self.last_temp = sensor_temp
Client.py
from src.temperature_sensor_thread import TemperatureSensorThread import queue # 使用线程安全的queue模块 import time temp_q: queue.Queue = queue.Queue() t = TemperatureSensorThread(q=temp_q) t.start() print('Setting temp 32') temp_q.put({'temp': 32}) print('Action: START') temp_q.put({'action': 'start'}) time.sleep(4) print('Action: STOP') temp_q.put({'action': 'stop'}) time.sleep(3) print('Temp: 41') temp_q.put({'temp': 41}) time.sleep(3) print('Action: START') temp_q.put({'action': 'start'}) time.sleep(3) print('Action: Exit') temp_q.put({'action': 'exit'}) time.sleep(5) print('Code exit')
额外说明
- 给
q.get()添加timeout并捕获queue.Empty异常,是为了避免线程在队列无消息时一直阻塞,让线程能周期性检查是否需要退出(也可以用q.get_nowait(),但需要处理异常)。 - 优化了消息处理的逻辑,让代码更清晰,避免不必要的三元表达式嵌套。
内容的提问来源于stack exchange,提问作者Vikas Gupta
相关产品推荐
相关产品推荐

