在浏览器中运行 Python 已经不算新鲜事,但让一个完整的 ASGI(异步服务器网关接口) 应用像在服务器端一样原生响应每一个网络请求,并自如地执行页面 JavaScript,却是困扰社区已久的难题。Simon Willison 在其博客上展示的新方案,终于填上了这块关键的拼图——通过将 Pyodide 与 Service Worker 结合,Python ASGI 应用得以在浏览器中真正“活”起来,古老的限制被连根拔起。
事件的核心要追溯到 Willison 的明星项目 Datasette Lite。该工具允许用户在浏览器里直接运行 Datasette,完全无需后端。但它长期被一个架构缺陷困扰:因为 Datasette 运行在 Web Worker 上下文中,无法直接访问 DOM,也不能执行 HTML 页面中通过 <script> 标签嵌入的 JavaScript。这意味着诸如自定义插件、交互式可视化等依赖动态脚本执行的能力几乎全部失效,严重削弱了 Datasette Lite 的实用性。此前基于 Web Worker 的方案,虽然能通过消息传递返回 HTML 内容,但脚本无法随页面加载而自然执行,开发者需要编写额外且受限的胶水代码,体验远不达原生。
新的解法一举将 Python 的运行环境抬高到了网络代理层。Willison 将 Pyodide Python 解释器加载到 Service Worker 中,并在那里启动一个真正的 ASGI 应用服务器。Service Worker 拦截页面所有的 fetch 请求,透传给运行中的 Python ASGI 应用,再将生成的响应返还给浏览器主线程。由于 Service Worker 本身就处于网络请求的必经路径上,它无需像 Worker 那样通过 postMessage 来回搬运,也自然拿到了对每一个资源请求的完全控制权。ASGI 应用的响应——包括完整的 HTML、CSS 以及最重要的内联 JavaScript——就像从远程服务器返回一样被浏览器解析和执行,所有脚本都能正常运行。这一过程得益于 ASGI 协议本身的事件驱动设计,使其天然适合与 Service Worker 的异步处理模型结合。
Willison 透露,该方案的开发得到了 Claude Opus 4.8 的辅助,并已给出两个可运行的演示:一个基础的 ASGI FastCGI 样例,以及一个运行 Datasette 1.0a31 的完整实例。两个演示都验证了内联脚本可执行、页面交互完整。这种能力让浏览器端 Python 不再是孤立的计算单元,而是一个可以自主处理路由、中间件、鉴权和渲染的完整 Web 服务端,只不过它完全运行在客户端沙箱中。在此之上,Willison 计划将这一架构应用于 Datasette Lite 的升级,届时所有依赖 JavaScript 的 Datasette 插件功能都将得到完整还原。
这一技术跨越对于 Pyodide 生态 意义重大。过去,浏览器 Python 常被框定在数据处理和科学计算的领域,与 UI 和交互层之间始终隔着一道墙;如今 Service Worker 的介入,让 Python 真正走进了“全栈浏览器应用”的核心。离线工具、无需服务器的教学环境、低延迟的数据探索仪表盘、甚至轻量级的内部工具原型,都将因此获得更强的交互表达力和更低的部署摩擦。当然,浏览器的 Pyodide 环境仍有内存和启动时间的约束,但架构瓶颈的消除无疑已经打开了一道新门。对于任何希望在浏览器中交付完整 Python 应用体验的开发者来说,Service Worker 补上的这一局,值得立即跟进试验。