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

如何通过按键中断函数执行及循环返回初始输入环节

实现按键中断子循环返回主菜单(Python标准库方案)

核心思路

通过后台线程监听按键+自定义异常/状态标记实现:

  1. 启动后台守护线程,持续监听目标按键(如ESC)
  2. 子循环运行时,定期检查中断标记,触发时跳出循环回到主菜单
  3. 全程使用Python标准库,无需第三方依赖

完整实现代码

import sys
import threading
import time

# 自定义异常,用于标记循环中断事件
class InterruptLoop(Exception):
    pass

# 跨平台非阻塞按键检测(标准库实现)
def is_key_pressed(target_key):
    if sys.platform.startswith('win'):
        import msvcrt
        return msvcrt.kbhit() and msvcrt.getch() == target_key.encode()
    else:
        import termios
        import tty
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setcbreak(fd)
            return sys.stdin.read(1) == target_key
        finally:
            # 恢复终端原有属性,避免异常
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)

# 全局中断事件,用于线程和主循环的通信
interrupt_event = threading.Event()

# 按键监听线程函数
def key_listener():
    while True:
        # 监听ESC键(ASCII码对应字符'\x1b')
        if is_key_pressed('\x1b'):
            interrupt_event.set()
            # 等待主循环处理完成后重置事件
            while interrupt_event.is_set():
                time.sleep(0.1)

# 示例业务函数
def perform_option1():
    print("Running option 1... Press ESC to return to menu")
    time.sleep(0.5)  # 模拟耗时操作

def perform_option2():
    print("Running option 2... Press ESC to return to menu")
    time.sleep(0.5)

def main():
    # 启动后台监听线程(守护线程,主程序退出时自动终止)
    listener_thread = threading.Thread(target=key_listener, daemon=True)
    listener_thread.start()

    while True:
        inp = input("\nEnter option (option_1/option_2/quit): ").strip()
        interrupt_event.clear()  # 重置中断标记

        if inp == "option_1":
            try:
                while True:
                    # 每次迭代前检查是否触发中断
                    if interrupt_event.is_set():
                        raise InterruptLoop()
                    perform_option1()
            except InterruptLoop:
                print("\nReturning to main menu...")
                interrupt_event.clear()

        elif inp == "option_2":
            try:
                while True:
                    if interrupt_event.is_set():
                        raise InterruptLoop()
                    perform_option2()
            except InterruptLoop:
                print("\nReturning to main menu...")
                interrupt_event.clear()

        elif inp == "quit":
            print("Exiting program...")
            sys.exit(0)

        else:
            print("Invalid option, try again.")

if __name__ == "__main__":
    main()

关键细节说明

  1. 跨平台兼容性:
    • Windows使用msvcrt库实现非阻塞按键检测
    • Linux/macOS使用termios和tty修改终端属性,实现非阻塞读取
  2. 线程通信:
    • 使用threading.Event作为线程和主循环的通信载体,避免全局变量的线程安全问题
    • 按键触发后设置事件,主循环检测到事件后抛出自定义异常跳出子循环
  3. 响应及时性:
    • 后台线程持续监听按键,不受主循环业务逻辑的阻塞影响
    • 若业务函数是CPU密集型操作,建议在函数内部插入interrupt_event检查,进一步提升响应速度
  4. 自定义异常:
    • 用异常标记中断逻辑,比直接break更清晰,也方便后续扩展错误处理逻辑

自定义修改点

  • 更换监听按键:将is_key_pressed('\x1b')中的'\x1b'替换为目标字符(如'q'对应Q键)
  • 调整响应频率:修改key_listener中的time.sleep(0.1)值,平衡CPU占用和响应速度

内容的提问来源于stack exchange,提问作者Bvdb89

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:35:41