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

如何在Python InquirerPy的select组件中获取触发按键与选项?

解决InquirerPy Select组件获取触发按键并执行后续提示的问题

要实现选中选项后根据触发按键运行新提示并返回原Select组件,同时获取选中项与触发按键,可以通过记录触发按键+暂停/恢复当前会话的方式解决事件循环冲突问题,具体实现如下:

可行代码实现

from InquirerPy import inquirer
from prompt_toolkit import Event

# 用于记录触发的功能按键
trigger_key = None

choices = ["Item 1", "Item 2", "Item 3"]  # 示例选项

prompt = inquirer.select(
    "Edit an item",
    mandatory=False,
    keybindings={
        "answer": [{"key": "enter"}],
        "skip": [{"key": "q"}]
    },
    choices=choices,
    long_instruction="'e' to edit, 'n' to insert after, 'i' to insert before, 'd' to delete current, 'p' to print, 'q' when finished",
)

# 注册各个功能键的处理函数
@prompt.register_kb("e")
def handle_edit(event: Event):
    global trigger_key
    trigger_key = "e"
    current_choice = prompt.selection  # 获取当前选中的选项
    # 暂停当前会话,避免事件循环冲突
    with prompt._session.pause():
        inquirer.text(f"Edit content for '{current_choice}':").execute()
    # 返回False阻止默认的answer行为,保持原Select组件活跃
    return False

@prompt.register_kb("i")
def handle_insert_before(event: Event):
    global trigger_key
    trigger_key = "i"
    current_choice = prompt.selection
    with prompt._session.pause():
        new_item = inquirer.text("Enter new item to insert before:").execute()
        if new_item:
            idx = choices.index(current_choice)
            choices.insert(idx, new_item)
            prompt.choices = choices  # 更新Select组件的选项
    return False

@prompt.register_kb("n")
def handle_insert_after(event: Event):
    global trigger_key
    trigger_key = "n"
    current_choice = prompt.selection
    with prompt._session.pause():
        new_item = inquirer.text("Enter new item to insert after:").execute()
        if new_item:
            idx = choices.index(current_choice)
            choices.insert(idx+1, new_item)
            prompt.choices = choices
    return False

@prompt.register_kb("d")
def handle_delete(event: Event):
    global trigger_key
    trigger_key = "d"
    current_choice = prompt.selection
    with prompt._session.pause():
        confirm = inquirer.confirm(f"Delete '{current_choice}'?").execute()
        if confirm:
            choices.remove(current_choice)
            prompt.choices = choices
    return False

@prompt.register_kb("p")
def handle_print(event: Event):
    global trigger_key
    trigger_key = "p"
    current_choice = prompt.selection
    with prompt._session.pause():
        inquirer.confirm(f"You selected to print '{current_choice}'", default=True).execute()
    return False

# 执行Select组件,当按q时退出
selected = prompt.execute()
# 最后可以查看退出时的选中项和触发按键(如果是enter触发的)
if selected:
    print(f"Final selected item: {selected}, trigger key: {trigger_key or 'enter'}")

对之前尝试方案的问题分析

方案1

无法获取事件/按键是因为prompt对象本身没有直接暴露事件属性,execute()返回的只是选中的选项,不会保留触发按键信息。

方案2

触发RuntimeError是因为在当前prompt的事件循环未结束时,直接启动了新的prompt,导致事件循环嵌套冲突。必须先暂停当前会话再运行新prompt。

方案3

调用prompt.answer()会直接结束当前Select组件,无法返回原组件继续操作,且同样没有解决事件循环冲突的问题。

核心思路说明

  • 使用全局变量trigger_key记录触发的功能按键,也可以用类实例属性替代全局变量更优雅。
  • 通过prompt._session.pause()暂停当前Select组件的会话,此时可以安全运行新的InquirerPy提示,完成后自动恢复原会话,保持原Select组件的状态。
  • 每个按键处理函数返回False,阻止InquirerPy执行默认的answer行为,避免Select组件直接退出,实现操作后返回原组件的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 09:46:03