CLI【免费下载链接】python-prompt-toolkitLibrary for building powerful interactive command line applications in Python项目地址https://gitcode.com/gh_mirrors/py/python-prompt-toolkit点击查看免费下载本文以官方升级文档 docs/pages/upgrading/3.0.rst 为骨架结合 prompt_toolkit 3.x 源码深入讲解从 2.0 升级到 3.0 的全部关键改动。升级到 prompt_toolkit 3.0 后库将原生运行在 asyncio 事件循环之上并且几乎全量引入了类型注解同时对话框dialog函数的返回类型与调用方式也发生了破坏性变更。读完本文你将掌握版本探测、事件循环 API 迁移、prompt_async()异步调用以及对话框run()/run_async()新用法的完整实战方案。一、3.0 的两大核心变化升级到 prompt_toolkit 3.0 时有两处影响全局的变化需要首先了解原生使用 asyncio 事件循环prompt_toolkit 不再维护自己实现的事件循环而是直接运行在 asyncio 之上。这意味着所有协程coroutine都成为真正的 asyncio 协程所有 Future 都是 asyncio Future异步生成器asynchronous generator也变成了真正的异步生成器。几乎全量类型注解代码库在几乎所有位置都加入了类型注解。这通常不会破坏任何已有代码但对 IDE 提示、静态类型检查和长期维护都大有裨益。除上述两点外还存在一些次要的破坏性变更其中最主要的是对话框dialogsAPI 的调整详见下文第五节。值得一提的是2.0 时代的迁移要点可以在 docs/pages/upgrading/2.0.rst 中找到那里记录了 Pygments 依赖移除、KeyBindingsManager移除、CommandLineInterface与Application合并等历史变化。3.0 的迁移正是建立在这些基础之上的。二、检测当前使用的 prompt_toolkit 版本在编写兼容 2.0/3.0 的代码时第一件事就是探测运行时版本。官方文档给出的方案如下from prompt_toolkit import __version__ as ptk_version PTK3 ptk_version.startswith(3.)在源码中__version__字符串与VERSION元组均由 src/prompt_toolkit/init.py 中的_load_version()通过importlib.metadata从已安装的发行版元数据中惰性加载因此该写法在所有合法安装方式pip、源码安装等下都可靠。除了startswith(3.)你也可以用更严格的比较from prompt_toolkit import VERSION PTK3 VERSION (3, 0, 0)三、修复对get_event_loop的调用2.0 时代prompt_toolkit 提供了自己的get_event_loop返回的是一个 prompt_toolkit 的EventLoop对象——它不是asyncio 事件循环只是 API 相似。3.0 中所有对get_event_loop的调用都必须修正。最简单的方式是按版本切换导入来源if PTK3: from asyncio import get_event_loop else: from prompt_toolkit.eventloop import get_event_loop事件循环 API 对照表升级过程中会用到的最常见 API 变化如下原文对照表版本 2.0prompt_toolkit EventLoop版本 3.0asyncioloop.run_in_executor(callback)loop.run_in_executor(None, callback)loop.call_from_executor(callback)loop.call_soon_threadsafe(callback)在 3.0 源码中这两条 API 的迁移痕迹清晰可见src/prompt_toolkit/eventloop/utils.py 中的run_in_executor_with_context(func, *args, loopNone)内部就是调用loop.run_in_executor(None, ctx.run, func, *args)——即executor参数显式传None并额外通过contextvars的ctx.run(...)保证回调运行在正确的上下文中同文件中的call_soon_threadsafe(func, max_postpone_timeNone, loopNone)则是对loop.call_soon_threadsafe(...)的封装。这些工具函数会从 src/prompt_toolkit/eventloop/init.py 导出。eventloop包在 3.0 中大幅瘦身目录 src/prompt_toolkit/eventloop 下仅保留async_generator.py、inputhook.py、utils.py、win32.py这正是不再自带事件循环实现、全面交给 asyncio的直接证据。四、运行在 asyncio 之上从async_True到prompt_async()2.0 时代若要运行在 asyncio 事件循环上需要显式调用from prompt_toolkit.eventloop.defaults import use_asyncio_event_loop use_asyncio_event_loop()在 3.0 中这已经是默认行为因此直接删除上面两行即可。不过仍然存在少量破坏性变更最典型的是异步调用的写法# For 2.0 result await PromptSession().prompt(Say something: , async_True)必须改写为# For 3.0 result await PromptSession().prompt_async(Say something: )为什么不能在协程里调用同步prompt()官方文档特别强调在 asyncio 应用即某个协程内部中不能调用同步的prompt()函数因为它会试图再次运行事件循环asyncio 不允许嵌套事件循环。此时必须始终使用prompt_async()。这一点在源码中有充分印证src/prompt_toolkit/shortcuts/prompt.py 中PromptSession.prompt_async()是真正的异步入口签名与同步版几乎一一对应message、editing_mode、completer、validator、multiline、bottom_toolbar等参数均可逐项覆盖传入官方自身的网络服务示例正是这样使用prompt_async的例如 src/prompt_toolkit/contrib/telnet/server.py 在interact协程中执行await session.prompt_async(messageSay something: )src/prompt_toolkit/contrib/ssh/server.py 的 SSH 交互回调同样使用await prompt_session.prompt_async(Type something: )作为对照同步prompt()最终也是通过Application.run()驱动而run()内部在无inputhook时调用asyncio.run(coro)见 src/prompt_toolkit/application/application.pyasyncio.run()在已有运行中事件循环的线程里会抛出RuntimeError——这正是不能在协程中调用的根本原因。五、对话框Dialog函数的破坏性变更这是 3.0 最需要注意的 API 变化。旧写法2.0from prompt_toolkit.shortcuts import input_dialog result input_dialog(title..., text...)在 2.0 中调用input_dialog()会直接弹出对话框并返回用户输入的结果。新写法3.03.0 中所有对话框函数返回的是一个 prompt_toolkitApplication对象你必须调用它的run或run_async方法才会真正显示对话框。同时async_参数在所有地方都被移除了。if PTK3: result input_dialog(title..., text...).run() else: result input_dialog(title..., text...) # 或者异步形式 if PTK3: result await input_dialog(title..., text...).run_async() else: result await input_dialog(title..., text..., async_True)源码层面的印证在 src/prompt_toolkit/shortcuts/dialogs.py 中__all__导出了 7 个对话框函数yes_no_dialog、button_dialog、input_dialog、message_dialog、radiolist_dialog、checkboxlist_dialog、progress_dialog。它们的签名全部带有返回类型注解- Application[...]yes_no_dialog(title, text, yes_textYes, no_textNo, styleNone) - Application[bool]dialogs.pyinput_dialog(title, text, ok_textOK, cancel_textCancel, completerNone, validatorNone, passwordFalse, styleNone, default) - Application[str | None]dialogs.py取消时返回Nonebutton_dialog(title, text, buttons, styleNone) - Application[_T]返回与所选按钮关联的值dialogs.py。也就是说返回 Application 对象并非文档的口头描述而是这些函数签名与实现的真实行为——例如yes_no_dialog通过get_app().exit(resultTrue/False)设置结果最终由_create_app(dialog, style)组装出一个完整的Application并返回。Application对象本身的两个运行入口是run(pre_runNone, set_exception_handlerTrue, handle_sigintTrue, in_threadFalse, inputhookNone)——阻塞式运行会在一个全新的 asyncio 事件循环中执行application.py。in_threadTrue时会在后台线程中新建并关闭事件循环适合确保不占用当前线程的事件循环ptpython 就使用了该能力run_async(pre_runNone, set_exception_handlerTrue, handle_sigintTrue, slow_callback_duration0.5)——协程入口是事件循环真正运行的唯一位置直到Application.exit()被调用才返回其结果application.py。在 asyncio 应用中使用对话框由于 SSH/Telnet 等异步场景下无法嵌套运行事件循环run_async是唯一选择。官方 SSH 示例就是这样处理对话框的src/prompt_toolkit/contrib/ssh/server.pyfrom prompt_toolkit.shortcuts import yes_no_dialog async def interact(...): if await yes_no_dialog(my title, my text).run_async(): # 用户点击了 Yes ...六、升级检查清单综合官方文档与源码从 2.0 升级到 3.0 的完整动作如下版本探测用from prompt_toolkit import __version__或VERSION判断当前是否为 3.x。删除use_asyncio_event_loop()相关两行——asyncio 已是默认事件循环。替换所有loop.run_in_executor(callback)为loop.run_in_executor(None, callback)。替换所有loop.call_from_executor(callback)为loop.call_soon_threadsafe(callback)或直接使用 eventloop/utils.py 中封装好的call_soon_threadsafe工具。import 切换from prompt_toolkit.eventloop import get_event_loop→from asyncio import get_event_loop。异步 promptawait PromptSession().prompt(..., async_True)→await PromptSession().prompt_async(...)绝不要在协程内部调用同步prompt()。对话框所有xxx_dialog(...)调用补上.run()或.run_async()移除async_True参数。类型注解红利升级后可以借助 mypy 等工具获得全量类型检查支持prompt_toolkit 仓库自带 py.typed 标记文件。如果遇到文档未覆盖的兼容性问题可参考仓库内真实使用prompt_async/run_async的示例telnet server、ssh server、choice_input核对写法这些都属于 3.0 时代的标准用法。赞分享CLI【免费下载链接】python-prompt-toolkitLibrary for building powerful interactive command line applications in Python项目地址https://gitcode.com/gh_mirrors/py/python-prompt-toolkit点击查看免费下载相关推荐从 prompt_toolkit 1.0 迁移到 2.0破坏性变更全解析与升级实战指南从 prompt_toolkit 1.0 迁移到 2.0破坏性变更全解析与升级实战指南 本文以官方升级文档 docs/pages/upgrading/2.0.CLI从 qiankun 2.x 迁移到 3.0完整升级指南与不兼容变更对照从 qiankun 2.x 迁移到 3.0完整升级指南与不兼容变更对照 本指南以 qiankun 3.0 的公开 API 精简、约束更明确的现实为起点逐项对前端微前端Litestar 3.0 升级迁移指南从 2.11 到 3.0 的破坏性变更全解析Litestar 3.0 升级迁移指南从 2.11 到 3.0 的破坏性变更全解析 本文以 Litestar 官方发布说明 docs/release note后端Web框架上一篇Ecctrl与Rapier物理引擎集成最佳实践碰撞检测与力反馈优化下一篇ESP32 CAMERA QR终极指南如何快速构建智能二维码扫描物联网设备创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
