PyScript Python in Browser
PyScript:在浏览器中运行 Python 的完全指南
欢迎来到 PyScript 的世界!本教程将带你从零开始,了解如何使用 PyScript 在网页中直接编写和运行 Python 代码。无需复杂的后端配置,只需浏览器,即可创建交互式的 Python 应用。
无论你是 Web 开发者还是 Python 爱好者,读完这篇教程,你都将能够:
- 在 HTML 文件中嵌入 Python 代码
- 操作 DOM,实现前端交互
- 利用 Python 生态中的常用库(如 NumPy、Matplotlib)
- 打包你的应用并分享给他人
1. 什么是 PyScript?
PyScript 是一个开源框架,它基于 Pyodide(一个将 CPython 编译到 WebAssembly 的项目),让你能在浏览器中直接运行 Python 代码。
它由 Anaconda 团队主导开发,旨在将 Python 的强大生态引入前端世界。
简单来说,过去你只能在服务器端使用 Python,然后通过 API 把结果传给浏览器;而现在,你可以把 Python 当成前端语言 来使用,直接在 <script> 标签中编写脚本,操作网页元素。
核心优势:
- 零安装:用户无需安装 Python 解释器,一切都运行在浏览器沙箱中。
- 与 HTML/CSS 无缝集成:Python 可以实时读写 DOM。
- 丰富的库支持:预置了大量科学计算和可视化库(Pyodide 项目维护了可运行在 WASM 上的包列表)。
- 简单部署:最终产物就是普通的 HTML 文件,上传到任何静态服务器即可。
2. 环境准备与第一个 PyScript 页面
你不需要安装任何软件,只需要一个现代浏览器(推荐 Chrome、Firefox 或 Edge)和一个代码编辑器(如 VS Code)。
2.1 一个最简单的例子
创建一个文件 hello.html,内容如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>我的第一个 PyScript 页面</title>
<link rel="stylesheet" href="https://pyscript.net/releases/2024.08.1/core.css">
<script type="module" src="https://pyscript.net/releases/2024.08.1/core.js"></script>
</head>
<body>
<h1>PyScript 演示</h1>
<py-script>
print("Hello, 浏览器中的 Python!")
</py-script>
</body>
</html>
用浏览器打开这个文件,你会看到:
- 页面上显示 “PyScript 演示”
- 同时在输出区域(默认是一个黑色终端风格的面板)中打印了
Hello, 浏览器中的 Python!
版本说明:本教程使用 PyScript 2024.08.1。如果日后有更新,请参考 官方文档 调整资源链接。
2.2 <py-script> 标签
<py-script> 是 PyScript 提供的最核心的自定义元素,所有放在这个标签内的代码都会被作为 Python 执行。
你可以在一页中放置多个 <py-script>,它们共享同一个全局命名空间。
3. 与网页元素交互
PyScript 可以像 JavaScript 一样操作 DOM,而且语法更加 Pythonic。
3.1 使用 Element 读写 HTML 元素
首先,你需要给目标元素一个 id 属性,然后在 Python 中通过 Element 类来获取它。
示例:制作一个点击计数器
<button id="my-btn" py-click="counter()">点击我!</button>
<p>点击次数:<span id="count-display">0</span></p>
<py-script>
count = 0
def counter():
global count
count += 1
Element("count-display").write(count)
</py-script>
代码解释:
py-click="counter()"是 PyScript 的事件绑定属性,当按钮被点击时执行 Python 函数。Element("count-display")获取 id 为count-display的元素。.write()方法设置该元素的文本内容。
3.2 获取用户输入
你也可以轻松读取输入框的值:
<input type="text" id="name-input" placeholder="输入你的名字">
<button id="greet-btn" py-click="greet()">打招呼</button>
<div id="greeting"></div>
<py-script>
def greet():
name = Element("name-input").value
greeting_text = f"你好,{name or '陌生人'}!"
Element("greeting").write(greeting_text)
</py-script>
3.3 常见事件属性
PyScript 支持一系列以 py- 开头的事件属性,可以直接内联在 HTML 元素上:
| 属性 | 触发时机 | 示例 |
|---|---|---|
py-click |
元素被点击时 | py-click="my_func()" |
py-change |
内容变化时(如输入框) | py-change="on_change()" |
py-keydown |
按键按下时 | py-keydown="on_key()" |
py-mouseover |
鼠标悬浮时 | py-mouseover="hover()" |
你还可以使用 when 装饰器实现更灵活的事件监听(后面会介绍)。
4. 使用 Python 库
PyScript 底层依赖 Pyodide,因此你可以直接使用 Pyodide 支持的第三方库。部分常用库(如 numpy, pandas, matplotlib)已经预加载,你可以在 <py-script> 中直接 import。
4.1 使用 NumPy 进行数学计算
<py-script>
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
result = np.mean(arr)
Element("numpy-result").write(f"平均值是: {result}")
</py-script>
<div id="numpy-result"></div>
4.2 绘制图表(Matplotlib)
使用 Matplotlib 时,需要稍微调整一下输出方式,让图像显示在网页上。
<div id="chart"></div>
<py-script>
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title("正弦波")
# 将图表渲染到 id 为 chart 的元素中
display(fig, target="chart", append=False)
</py-script>
display() 函数是 PyScript 提供的,可以从 Python 向 HTML 输出多种对象,包括 Matplotlib 图像。
提示:如果你想使用未被预装的库(如
requests),可以使用<py-config>标签手动加载,或者通过micropip在运行时安装。
5. 使用 <py-config> 配置环境
<py-config> 标签用于声明 Python 环境配置,比如要额外安装的包、本地文件路径等。将它放在 <head> 或 <body> 的最前面。
5.1 安装第三方包
例如,你需要使用 requests 库:
<py-config>
packages = ["requests"]
</py-config>
<py-script>
import requests
response = requests.get("https://api.github.com")
print("GitHub API 状态码:", response.status_code)
</py-script>
<py-config> 内采用 TOML 格式。更复杂的配置可以这样写:
<py-config>
[splashscreen]
enabled = false
[[fetch]]
files = ["./data.csv"]
</py-config>
5.2 加载本地文件
如果你的应用需要读取用户上传的文件或本地数据,可以使用 [[fetch]] 声明文件列表,PyScript 会在运行时将其加载到虚拟文件系统中,供 Python 代码访问。
6. 深入事件处理:when 装饰器
除了内联的 py-* 属性,PyScript 还提供了更现代的 when 装饰器,可以在纯 Python 代码中绑定事件。
示例:通过 when 实现按钮点击
<button id="decorated-btn">点击我(装饰器版)</button>
<div id="decorated-output"></div>
<py-script>
from pyscript import when
@when("click", "#decorated-btn")
def on_click(event):
Element("decorated-output").write("你点击了按钮!")
</py-script>
@when 接收两个参数:事件类型和选择器(CSS 选择器,如 #id, .class)。
这种方式使逻辑与 HTML 标记更解耦,尤其适合复杂的 Web 应用。
7. 创建实时交互应用:一个完整示例
让我们结合上述知识点,构建一个简单的 待办事项(Todo)列表 应用。
完整代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>PyScript 待办事项</title>
<link rel="stylesheet" href="https://pyscript.net/releases/2024.08.1/core.css">
<script type="module" src="https://pyscript.net/releases/2024.08.1/core.js"></script>
</head>
<body>
<h2>📝 我的待办事项</h2>
<input type="text" id="task-input" placeholder="输入任务...">
<button id="add-btn">添加</button>
<ul id="task-list"></ul>
<py-script>
from pyscript import when, Element
tasks = []
def render_tasks():
task_list_element = Element("task-list")
# 清空当前列表
task_list_element.clear()
for idx, task in enumerate(tasks):
li = document.createElement("li") # 可以直接使用 document 对象
li.innerHTML = f"{task} <button class='delete-btn' data-index='{idx}'>删除</button>"
task_list_element.element.appendChild(li)
@when("click", "#add-btn")
def add_task(evt):
input_element = Element("task-input")
task_text = input_element.value.strip()
if task_text:
tasks.append(task_text)
input_element.clear()
render_tasks()
@when("click", ".delete-btn") # 动态创建的元素也能绑定(事件委托有效)
def delete_task(evt):
# 从按钮的 data-index 属性获取删除的任务索引
index = int(evt.target.getAttribute("data-index"))
tasks.pop(index)
render_tasks()
</py-script>
</body>
</html>
操作说明:
- 在输入框中输入任务名称,点击“添加”,任务会出现在下方列表。
- 每个任务右侧有一个“删除”按钮,点击即可移除对应任务。
- 任务列表由 Python 列表
tasks驱动,每次操作后重新渲染。
注意:这里我们使用了
document对象,它是 PyScript 全局可用的浏览器 Document 对象,允许你使用熟悉的 DOM API。
8. 调试与常见问题
8.1 查看输出与错误
默认情况下,print() 的输出和 Python 异常会显示在页面下方的终端面板中。
如果面板被隐藏,可以按 Ctrl+Shift+O (Windows/Linux) 或 Cmd+Shift+O (Mac) 打开开发者控制台查看错误。
8.2 加载速度慢怎么办?
初次加载 PyScript 页面时,浏览器需要下载 Pyodide 运行时(约 8-12 MB),可能会有几秒延迟。
优化建议:
- 使用 CDN 加速(本教程使用的已经是)。
- 在
<py-config>中设置preload列表,仅加载真正用到的包。 - 提供友好的加载提示(可以通过
<py-splashscreen>自定义启动画面)。
8.3 想使用 input() 函数?
PyScript 默认的 input() 是阻塞式的,并不适合浏览器环境。你应该使用 HTML 输入框并通过事件读取值,就像前面示例那样。
9. 部署与分享
你完成的 PyScript 应用就是一个静态网站,只需要把它托管到任意 HTTP 服务器即可。
几种简单的方式:
- 本地测试:直接用浏览器打开 HTML 文件(某些功能可能需要通过 HTTP 服务才能正常工作,推荐使用 VS Code 的 Live Server 插件)。
- 在线发布:上传到 GitHub Pages、Netlify、Vercel 等静态托管平台。
无需后端代码,无需配置 Python 环境,用户只要能访问网页就能使用你的应用。
10. 局限性与未来
虽然 PyScript 打开了新的大门,但目前仍有以下限制:
- 执行效率不如原生编译,大量计算任务可能较慢(但 WebAssembly 在持续优化)。
- 库支持依賴 Pyodide 包的移植,不是所有 Python 包都能用。
- 包体积较大,初次访问等待时间较长。
- 无法调用客户端系统 API,受浏览器安全策略限制。
尽管如此,PyScript 正在快速发展,社区生态也在不断完善。对于教育、数据演示、轻量级工具等场景,它已经足够强大。
结语
恭喜你完成了 PyScript 的基础入门!你现在已经能够:
- 在网页中运行 Python 并操作 DOM
- 使用 numpy、matplotlib 等常用库
- 构建交互式的 Todo 应用
- 了解配置、事件处理和部署方法
下一步,你可以尝试:
- 阅读 PyScript 官方文档
- 探索 Pyodide 可用包列表
- 把现有的 Python 小工具改写成网页版,分享给朋友
用 Python 重塑网页体验,现在就开始吧!