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

如何将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())

关键改进点

  1. 替换阻塞API:用keyboard.on_press回调监听所有按键,配合异步休眠保持任务存活,彻底避免阻塞事件循环。
  2. 修复异步休眠:把sleep改成异步函数并添加await,确保延迟生效;补全random模块导入。
  3. 优雅退出:用asyncio.get_running_loop().stop()终止事件循环,替代粗暴的exit()。
  4. 降低CPU占用:record_stop()里添加await asyncio.sleep(0.01),让出CPU资源,避免循环空转。

内容的提问来源于stack exchange,提问作者송형준

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 23:55:19