如何将keyboard模块功能融入异步代码?代码故障排查
问题排查与修复
原代码核心问题
- 阻塞式API卡死事件循环:
keyboard.read_key()是同步阻塞方法,一旦record_start()执行到这行,会直接卡住整个异步事件循环,导致record_stop()完全无法运行。 - 异步方法调用错误:
sleep函数里调用asyncio.sleep()但未加await,且函数本身不是异步函数,根本不会产生延迟效果;同时遗漏了random模块的导入,运行会直接报错。 - 重复按键读取:
record_start()里连续两次调用keyboard.read_key(),导致每按一次键需要触发两次输入才会打印,属于无效逻辑。 - 粗暴退出异步环境:用同步的
exit()终止程序,会破坏异步事件循环的正常关闭流程。
修复后的代码
import keyboard import asyncio import random async def async_sleep(a): rand1 = random.uniform(0, 0.009) rand2 = random.uniform(0.01, 0.02) result = random.uniform(rand1, rand2) await asyncio.sleep(a + result) async def record_start(): # 用回调监听所有按键,避免阻塞事件循环 def on_key_press(event): print(event.name) keyboard.on_press(on_key_press) # 保持任务存活,否则asyncio会退出 while True: await asyncio.sleep(1) async def record_stop(): while True: # 改用非阻塞的按键检查,配合asyncio.sleep让出事件循环 if keyboard.is_pressed('0'): print('stop') await async_sleep(1) # 优雅终止异步事件循环 asyncio.get_running_loop().stop() return await asyncio.sleep(0.01) # 让出CPU,避免占用过高 async def main(): await asyncio.gather( record_stop(), record_start(), ) asyncio.run(main())
关键改进点
- 替换阻塞API:用
keyboard.on_press回调监听所有按键,配合异步休眠保持任务存活,彻底避免阻塞事件循环。 - 修复异步休眠:把
sleep改成异步函数并添加await,确保延迟生效;补全random模块导入。 - 优雅退出:用
asyncio.get_running_loop().stop()终止事件循环,替代粗暴的exit()。 - 降低CPU占用:
record_stop()里添加await asyncio.sleep(0.01),让出CPU资源,避免循环空转。
内容的提问来源于stack exchange,提问作者송형준
相关产品推荐
相关产品推荐

