如何在Python线程中后台运行两个协程?
问题分析与修复方案
核心问题
你的代码无法正常打印消息,主要有两个关键问题:
- 同步阻塞调用卡住事件循环:
heartbeat里用了time.sleep(30),这是同步阻塞函数,会彻底卡住asyncio事件循环,导致listen协程完全没有机会执行消息监听操作。 - client初始化顺序错误:当前代码先启动线程再初始化
client,线程内的协程会访问到未初始化的client,引发错误或异常。
修复后的代码
import threading import asyncio async def heartbeat(client): while True: await client.websok.send_message('\n') # 替换同步sleep为异步的asyncio.sleep,不阻塞事件循环 await asyncio.sleep(30) async def listen(client): while True: msg = await client.websok.receive_message() print(msg) def background_loop(client): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) tasks = [heartbeat(client), listen(client)] loop.run_until_complete(asyncio.gather(*tasks)) # Main code # 先初始化client,确保线程启动前client已经就绪 client = # 这里完成你的API连接创建逻辑 # 将client作为参数传入线程函数,避免全局变量的潜在问题 t = threading.Thread(target=background_loop, args=(client,)) t.start()
关键修改说明
- 替换
time.sleep为asyncio.sleep:asyncio.sleep是异步非阻塞的,只会让当前协程暂停,事件循环可以在这段时间去执行listen协程的消息监听操作。 - 调整client初始化顺序:先完成
client的创建,再启动线程,确保线程内的协程能访问到已就绪的连接对象。 - 将client作为参数传入线程函数:避免使用全局变量,减少多线程环境下的变量访问风险,让代码逻辑更清晰。
内容的提问来源于stack exchange,提问作者Mak_3000
相关产品推荐
相关产品推荐

