如何在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
相关产品推荐
相关产品推荐

