ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

pywebview 版本演进全解:从 3.0 到 6.0 的核心特性、API 迁移与源码级实践指南

pywebview 版本演进全解:从 3.0 到 6.0 的核心特性、API 迁移与源码级实践指南 桌面应用前端【免费下载链接】pywebviewBuild GUI for your Python program with JavaScript, HTML, and CSS项目地址https://gitcode.com/gh_mirrors/py/pywebview点击查看免费下载本文以 pywebview 官方博客docs/blog发布的三个里程碑版本公告为主体系统梳理 pywebview 3.0、5.0、6.0 各自带来的核心能力——从webview.start()与现代窗口对象的确立到 Android 与 DOM 支持的落地再到共享状态管理与网络事件监控的引入。文章在完整继承官方公告内容的基础上结合本仓库的源码实现webview/state.py、webview/event.py、webview/menu.py、webview/init.py 等逐一印证每个特性的底层原理帮助读者既掌握每个版本的实操写法又理解其设计动机与迁移路径能够在自己的项目中正确选用对应 API。pywebview 是什么pywebview 是一个轻量级的 Python GUI 框架让你可以用 HTML、CSS 和 JavaScript 来构建 Python 程序的桌面界面同时尽可能隐藏界面其实运行在浏览器里这一事实。可以把它理解为轻量级的 Electron——但与 Electron 不同pywebview 不捆绑任何 Web 渲染引擎而是直接复用操作系统自带的原生 webviewWindows 上的 EdgeChromium/MSHTML、macOS 上的 WKWebView、Linux 上的 GTK WebKit以及 Android 的 WebView因此产出的二进制体积更小、性能更好。编写一次 UI即可在 Windows、macOS、Linux 与 Android 上部署并完全保有 Python 的全部能力。安装方式pip install pywebview以下按发布时间顺序回顾 pywebview 3.02019、5.02024与 6.02025三个版本的核心演进。pywebview 6共享状态、网络事件与窗口级菜单6.0 是 pywebview 的又一次大版本迭代带来了强大的状态管理、网络事件处理和显著的 Android 支持改进。共享状态管理window.state6.0 最引人注目的特性是通过window.state对象实现的共享状态管理它在 JavaScript 与 Python 之间自动同步状态免去了手工同步数据的繁琐。# In Python window.state.user_name Test// In Javascript - automatically updated! console.log(window.pywebview.state.user_name); // Test这种双向同步让复杂应用的构建简单得多。不过目前状态同步仅限于顶层属性如果要同步嵌套对象需要整体重新赋值整个对象# In Python window.state.user_settings {theme: dark, notifications: True}// In Javascript - automatically updated! console.log(window.pywebview.state.user_settings); // {theme: dark, notifications: True} window.pywebview.state.user_settings {theme: light, notifications: False} // Updates Python side too源码级原理。在 webview/state.py 中State类继承自dict重写了__setattr__/__setitem__/__delattr__/__delitem__。每当 Python 侧赋值或删除状态就会调用__update_js生成一段形如window.pywebview.state.__pywebviewHaltUpdate__xxx JSON.parse(...)的脚本并通过window.run_js注入webview/state.py反过来JavaScript 侧的赋值通过pywebviewStateUpdate回调回到 Python。JS 侧的实现位于 webview/js/state.js它用Proxy包装一个EventTarget在set陷阱中先分发CustomEvent(change)再通过_jsApiCallback(pywebviewStateUpdate, ...)通知 PythondeleteProperty陷阱则对应pywebviewStateDelete。特殊前缀__pywebviewHaltUpdate__用于标识来自对端、无需回传的更新避免同步死循环。此外State支持用/-注册或移除状态变更处理器收到change/delete事件类型、变更键名与值Python 侧还可以通过del window.state.key或字典式写法window.state[key] value操作状态。网络事件request_sent与response_received6.0 引入了强大的网络监控能力。request_sent与response_received事件会在每次 HTTP 请求发生时触发让你对应用网络活动有完全的可见性请求头可在发送前修改响应可在到达时检视。需要注意响应头修改不受支持。def on_request_sent(request): print(fSending request to: {request[url]}) # Modify request headers before sending request[headers][Authorization] fBearer {get_auth_token()} def on_response_received(response): print(fReceived response: {response[status_code]}) window.events.request_sent on_request_sent window.events.response_received on_response_received源码级原理。事件挂载在 webview/window.py 的Window.events上self.events.request_sent Event(self)、self.events.response_received Event(self)而Event类定义于 webview/event.py它用/-管理处理器列表set()时把每个处理器放到独立线程执行并收集返回值。各平台接入点分散于 webview/platforms/cocoa.py约 L319-L324、L356 处调用request_sent.set(request_)/response_received.set(response)、webview/platforms/edgechromium.py约 L367、L375、webview/platforms/gtk.py约 L391-L397以及 webview/platforms/android/init.py约 L101、L179、L196。这印证了请求头可改、响应可读的能力是在各平台 WebView 的请求拦截回调中实现的。initialized事件另一个新事件是initialized它在 GUI 库或 webview 渲染器被选定之后、窗口创建之前触发。这允许你根据选中的渲染器定制行为或通过让事件处理器返回False来中止整个执行流程。def on_initialized(renderer): print(fInitialized with renderer: {renderer}) window.events.initialized on_initialized源码级原理。在 webview/window.py 的_initialize中abort self.events.initialized.set(gui.renderer); return not abort——处理器若返回FalseEvent.set()会收集所有处理器返回值并判定存在False从而中止窗口初始化。对应地webview.create_window在初始化被取消时会返回None见 webview/init.py 中create_window的 docstringreturn window object or None if window initialization is cancelled in the window.events.initialized event。窗口级菜单6.0 允许为单个窗口创建自定义菜单让你对界面拥有更多控制GTK 且使用 Unity 桌面时不受支持。menu webview.menu.Menu([ webview.menu.MenuAction(File, [ webview.menu.MenuAction(New, new_file), webview.menu.MenuSeparator(), webview.menu.MenuAction(Exit, exit_app) ]) ]) window webview.create_window(My App, index.html, menumenu)源码级原理。菜单的三类构建块定义于 webview/menu.pyMenu(title, items)表示菜单或子菜单MenuAction(title, function)绑定点击回调MenuSeparator()表示分隔线create_window的menu参数类型为list[Menu]见 webview/window.py。现代化 API 改进破坏性变更6.0 包含若干打破兼容的变更用以现代化 API 并移除废弃功能文件对话框常量现在归属于webview.FileDialog枚举SAVE、LOAD、FOLDER枚举定义见 webview/init.pyFileDialog.OPEN 10、FileDialog.FOLDER 20、FileDialog.SAVE 30注意旧常量OPEN_DIALOG/FOLDER_DIALOG/SAVE_DIALOG已被标记为废弃并会在未来版本移除。webview.DRAG_REGION_SELECTOR移动至webview.settings[DRAG_REGION_SELECTOR]原模块级属性目前仅返回设置值并打印废弃警告见 webview/init.py。废弃的 DOM 函数被移除统一使用现代的window.domAPI。平台专项增强Windows支持深色模式并可自动检测系统主题。macOS可隐藏默认菜单JavaScript prompt 处理得到改进。所有平台屏幕坐标处理改进SSL 支持增强。pywebview 5Android、DOM 与应用设置5.0 带来三大核心特性Android 支持、DOM 操作与应用程序设置。Android 支持现在可以把 pywebview 应用直接运行在 Android 设备上。移动端体验有一些固有局限不支持窗口操作、多窗口与文件对话框其余能力与其它平台一致。打包 Android 应用的完整步骤见 docs/guide/freezing.md官方公告中指向 Freezing 指南。仓库中还提供了专门的 Android 测试套件位于 tests/android其中包含事件、JS API、状态与窗口等测试脚本test-events.js、test-js-api.js、test-state.js、test-window.js以及完整的 Android 工程代码与平台实现webview/platforms/android。DOM 支持借助 DOM 支持你可以像 jQuery 那样在 Python 侧直接进行 DOM 操作、遍历与事件处理还可以读写元素的属性、样式与 class。Element对象在 Python 中代表一个 DOM 节点由window.dom.get_element、window.dom.get_elements和window.dom.create_element返回window.dom.body、window.dom.document与window.dom.window则分别暴露了 body、document 与 window。新的 JavaScript 序列化器可以序列化更多 JS 对象类型并处理循环依赖。window.dom.document.events.scroll lambda e: print(window.dom.window.node[scrollY]) button window.dom.create_element(button disabled classhiddenButton/button, window.dom.body) button.style[width] 200px button.attributes { disabled: False } button.events.click click_handler button.classes.toggle(hidden)完整的实战示例可参考仓库中的 examples/dom_events.py、examples/dom_manipulation.py 与 examples/dom_traversal.py。DOM 的 Python 侧实现位于 webview/domdom.py、element.py、event.py、classlist.py等序列化相关的 JavaScript 桥接代码位于 webview/js/lib/dom_json.js。顺带一提社区呼声很高的拖放获取完整文件路径也在 5.0 落地pywebview 为DropEvent增加了event[dataTransfer][files][0][pywebviewFullPath]字段提供被拖入文件的绝对路径。该完整路径只在 Python 侧可用。应用设置webview.settingspywebview 对默认体验相当有主见。多年来作者收到大量要求改变默认行为的请求应用设置机制让这一切成为可能。5.0 引入webview.settings字典官方公告中的基础选项如下webview.settings { ALLOW_DOWNLOADS: False, # Allow file downloads ALLOW_FILE_URLS: True, # Allow access to file:// urls OPEN_EXTERNAL_LINKS_IN_BROWSER: True, # Open target_blank links in an external browser OPEN_DEVTOOLS_IN_DEBUG: True, # Automatically open devtools when start(debugTrue). }应用设置必须在调用webview.start()之前设置才能生效。源码级补充。当前仓库中settings的完整定义位于 webview/init.py在 5.0 基础上还扩展了更多选项一并列出便于查阅设置键默认值含义ALLOW_DOWNLOADSFalse是否允许文件下载ALLOW_FILE_URLSTrue是否允许访问file://链接DRAG_REGION_SELECTOR.pywebview-drag-region可拖拽区域的选择器6.0 起从模块级属性迁移至此DRAG_REGION_DIRECT_TARGET_ONLYFalse仅直接命中拖拽区域时才响应拖拽DEFAULT_HTTP_PORT42001内置 HTTP 服务器的默认端口OPEN_EXTERNAL_LINKS_IN_BROWSERTruetarget_blank链接是否在外部浏览器打开OPEN_DEVTOOLS_IN_DEBUGTruestart(debugTrue)时是否自动打开开发者工具REMOTE_DEBUGGING_PORTNone远程调试端口None表示不启用IGNORE_SSL_ERRORSFalse是否忽略 SSL 错误JS_API_MAX_DEPTH10JS API 返回值的最大序列化深度SHOW_DEFAULT_MENUSTrue是否显示默认菜单macOSWEBVIEW2_RUNTIME_PATHNone自定义 WebView2 运行时路径这些设置在平台实现中被消费例如ALLOW_DOWNLOADS在 webview/platforms/cocoa.py约 L299、L359、webview/platforms/edgechromium.py约 L327、webview/platforms/gtk.py约 L214与 webview/platforms/android/init.py约 L137中控制下载行为OPEN_DEVTOOLS_IN_DEBUG在 debug 模式下决定是否弹出开发者工具如 webview/platforms/cef.py 约 L331。pywebview 3现代 API 的奠基3.0 是第一个与之前版本不兼容的版本。2.x 引入的多窗口支持带来了一些值得商榷的架构决策3.0 重新理顺了这些设计。webview.start()与窗口对象最大的变化是引入了窗口对象与webview.start()函数。过去GUI 事件循环由第一次调用webview.create_window()隐式启动——create_window一函数二用既创建窗口又启动事件循环更令人困惑的是第一次调用是阻塞的而子线程中的后续调用却不阻塞。现在create_window无论调用多少次都只创建窗口并返回窗口对象且永远不阻塞。请记住在 GUI 事件循环启动之前窗口不会显示。用新 API 写出的 hello worldimport webview window webview.create_window(Hello world, https://pywebview.flowrl.com/hello) webview.start()webview.start还提供了便捷方式在 GUI 事件循环启动后执行线程相关代码免去线程样板代码import webview def change_title(window): window.change_title(pywebview whoa) window webview.create_window(pywebview wow, https://pywebview.flowrl.com/hello) webview.start(change_title, window)窗口对象所有与窗口管理和 Web 内容相关的函数都移动到了webview.create_window返回的窗口对象上。例如webview.load_html变成了window.load_htmlimport webview def load_html(window): window.load_html(htmlbodyh1pywebview wow!/h1body/html) window webview.create_window(pywebview wow) webview.start(load_html, window)在现代版本中Window对象还集成了events事件容器、domDOM 对象与state状态对象见 webview/window.py是后续版本所有 API 的汇聚点。内置 HTTP 服务器pywebview 现在自带 HTTP 服务器用于托管本地静态文件。出于混淆目的服务器默认运行在随机端口上。import webview window webview.create_window(pywebview wow, assets/index.html) webview.start(http_serverTrue)事件系统3.0 引入了新的事件系统支持订阅/退订事件当时实现了shown与loaded两个事件事件对象由窗口对象提供。用法示例见 examples/events.py。这一事件系统在后续版本中持续扩展——到 6.0 已包含closed、closing、before_load、initialized、minimized、maximized、resized、moved、request_sent、response_received等十余种事件webview/window.py。Edge 支持Windows 平台新增对 EdgeHTML 的支持。满足系统要求.NET 4.6.2 与 Windows 10 1803时自动选用 EdgeHTML。需要说明的是当时 EdgeHTML尚无法访问本地文件因此必须使用 HTTP 服务器如果希望强制使用 MSHTML可以webview.start(guimshtml)。create_window可直接加载 HTMLimport webview window webview.create_window(pywebview wow, htmlhtmlbodyh1pywebview wow!/h1body/html) webview.start()如果同时提供url与html参数html优先。get_elements现在可以用window.get_elements(selector)检索 DOM 节点节点由 domJSON 库序列化。示例见 examples/get_elements.py。该能力在 5.0 中被更完整的window.domAPI 取代。webview.config已移除webview.config不复存在。要指定 GUI 渲染器使用webview.start的gui参数。confirm_quit更名为confirm_close例如webview.create_window(Window, confirm_closeTrue)。从 3.0 到 6.0 的迁移速查旧写法新写法引入版本create_window()隐式启动事件循环create_window()webview.start()3.0webview.load_html(...)window.load_html(...)3.0webview.configwebview.start(gui...)等3.0confirm_quitTrueconfirm_closeTrue3.0webview.OPEN_DIALOG/FOLDER_DIALOG/SAVE_DIALOGwebview.FileDialog.OPEN/FOLDER/SAVE6.0webview.DRAG_REGION_SELECTORwebview.settings[DRAG_REGION_SELECTOR]6.0旧式 DOM 辅助函数window.domAPIget_element、create_element等5.0 / 6.0深入学习与验证官方公告原文docs/blog/pywebview6.md、docs/blog/pywebview5.md、docs/blog/pywebview3.md完整变更日志docs/CHANGELOG.md使用指南docs/guide/usage.md安装与平台选择docs/guide/installation.md、docs/guide/web_engine.mdAPI 参考docs/api/README.md实战示例仓库 examples 目录state.py、dom_events.py、dom_manipulation.py、dom_traversal.py、events.py、get_elements.py、menu.py等逐一对应上文特性源码实现webview/state.py、webview/js/state.js、webview/event.py、webview/menu.py、webview/dom、webview/platformsAndroid 打包docs/guide/freezing.md赞分享桌面应用前端【免费下载链接】pywebviewBuild GUI for your Python program with JavaScript, HTML, and CSS项目地址https://gitcode.com/gh_mirrors/py/pywebview点击查看免费下载相关推荐Dash DataTable 版本演进全解从 3.0 到 4.12 的 API 重构与核心特性变迁Dash DataTable 版本演进全解从 3.0 到 4.12 的 API 重构与核心特性变迁 Dash DataTable dash_table.Da前端后端数据可视化flutter_riverpod 全版本演进解析从 0.1.0 到 3.4.3 的 API 变迁与 Riverpod 3.0 核心特性flutter_riverpod 全版本演进解析从 0.1.0 到 3.4.3 的 API 变迁与 Riverpod 3.0 核心特性 本篇文章基于仓库内 f前端移动开发CacheCloud 的 Redis 版本演进指南从 3.0 到 6.0 的关键特性与平台版本升级实践CacheCloud 的 Redis 版本演进指南从 3.0 到 6.0 的关键特性与平台版本升级实践 本文以 CacheCloud 官方 Wiki 中《re后端运维上一篇深入解析 wp-calypso 的 Spinner 加载指示组件API 用法、源码原理与设计哲学下一篇合法括号字符串通用解题思路与双指针区间维护2116 判断一个括号字符串是否有效创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进