在网页中直接运行Python代码且不需要服务器支持,核心思路是利用WebAssembly技术将Python解释器移植到浏览器环境中,目前最成熟的方案是借助Pyodide实现。Pyodide是Mozilla开发的项目,它把Python解释器和常用的科学计算库都编译成了WebAssembly格式,能在浏览器里完整运行Python代码,不需要和后端服务器做任何交互。

核心实现原理
Pyodide的工作流程主要分为几个步骤,首先浏览器加载Pyodide的运行时文件,这部分文件包含了编译后的Python解释器核心。接着运行时会在浏览器的内存中初始化一个独立的Python执行环境,这个环境和浏览器的JavaScript环境是相互隔离的,但是可以通过特定的API进行数据交互。当用户输入Python代码后,Pyodide会把代码交给内存中的Python解释器执行,执行结果再返回给前端页面展示。
基础环境引入
要在网页中使用Pyodide,首先需要在HTML页面中引入Pyodide的CDN资源,不需要做任何服务器端的配置,直接通过公共CDN加载即可。引入完成后需要等待Pyodide初始化完成,才能调用相关的API执行Python代码。
下面是引入Pyodide的基础HTML代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网页运行Python代码</title>
</head>
<body>
<!-- 引入Pyodide CDN -->
<script src="https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js"></script>
<script>
// 后续逻辑写在这里
</script>
</body>
</html>
执行简单Python代码
Pyodide初始化完成后,会提供一个pyodide全局对象,通过这个对象的runPython方法就可以执行Python代码字符串,方法会返回Python代码的执行结果。需要注意的是初始化是异步过程,所以需要用async/await语法处理。
下面的示例实现了一个简单的功能,在网页中执行Python的加法计算,并把结果展示在页面上:
async function runPythonCode() {
// 等待Pyodide初始化完成
let pyodide = await loadPyodide();
// 要执行的Python代码
let pythonCode = `
a = 10
b = 20
result = a + b
result
`;
// 执行Python代码并获取结果
let output = pyodide.runPython(pythonCode);
// 把结果展示到页面
document.getElementById("output").innerText = "计算结果:" + output;
}
// 页面加载完成后初始化
window.onload = function() {
runPythonCode();
};
对应的HTML展示部分代码:
<div>
<p>Python执行结果区域:</p>
<p id="output"></p>
</div>
处理Python的输入输出
如果Python代码中包含print输出或者需要获取用户输入,需要做额外的处理。Pyodide默认不会把print的内容直接返回,我们可以通过重定向标准输出来捕获这些内容。而对于输入,我们可以给Python环境注入自定义的函数来处理。
捕获print输出
下面的示例演示如何捕获Python代码中print的内容:
async function runPythonWithPrint() {
let pyodide = await loadPyodide();
// 存储print输出的数组
let outputList = [];
// 重定向标准输出,把print的内容存入数组
pyodide.setStdout({
write: (text) => {
outputList.push(text);
}
});
let pythonCode = `
print("Hello from Python")
print("当前Python版本:", "3.11")
x = 5 * 6
print("5乘以6的结果是:", x)
`;
pyodide.runPython(pythonCode);
// 拼接所有输出内容
document.getElementById("printOutput").innerText = outputList.join("");
}
模拟input输入
如果Python代码中用到了input函数,我们可以通过给Pyodide注入input函数的方式来模拟用户输入,下面的示例展示了如何实现:
async function runPythonWithInput() {
let pyodide = await loadPyodide();
// 模拟input函数,返回预设的输入值
pyodide.globals.set("input", () => {
return "测试输入内容";
});
let pythonCode = `
user_input = input("请输入内容:")
print("你输入的内容是:", user_input)
`;
let outputList = [];
pyodide.setStdout({
write: (text) => {
outputList.push(text);
}
});
pyodide.runPython(pythonCode);
document.getElementById("inputOutput").innerText = outputList.join("");
}
安装Python第三方库
Pyodide默认已经包含了很多常用的Python库,比如numpy、pandas、matplotlib等,如果需要使用额外的库,可以通过pyodide.loadPackage方法加载,加载完成后就可以在Python代码中正常导入使用。
下面的示例演示如何加载numpy库并使用:
async function runPythonWithLib() {
let pyodide = await loadPyodide();
// 加载numpy库,加载是异步过程
await pyodide.loadPackage("numpy");
let pythonCode = `
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
mean_value = np.mean(arr)
mean_value
`;
let result = pyodide.runPython(pythonCode);
document.getElementById("libOutput").innerText = "数组平均值:" + result;
}
注意事项
- Pyodide的初始化文件体积比较大,首次加载可能需要几秒钟时间,建议添加加载状态提示,提升用户体验。
- 浏览器环境的内存有限,不适合运行非常消耗资源的Python代码,比如处理超大文件或者复杂的机器学习训练任务。
- 不同的Pyodide版本支持的Python库可能有差异,使用前可以查看对应版本的官方文档确认支持的库列表。
- Pyodide运行在浏览器沙箱中,无法直接访问用户的本地文件系统,所有文件操作只能在浏览器分配的内存空间中进行。
完整示例页面
下面是一个完整的可运行页面代码,整合了上述的功能,用户可以直接把代码保存为HTML文件,用浏览器打开即可测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网页直接运行Python代码</title>
<style>
.container { max-width: 800px; margin: 20px auto; padding: 0 20px; }
.section { margin: 20px 0; padding: 15px; border: 1px solid #eee; }
button { padding: 8px 16px; margin: 5px; cursor: pointer; }
.output { min-height: 40px; padding: 10px; background: #f5f5f5; margin-top: 10px; }
</style>
</head>
<body>
<div class="container">
<h1>网页无服务器运行Python代码</h1>
<div class="section">
<h3>基础计算</h3>
<button onclick="runBasic()">执行基础计算</button>
<div class="output" id="basicOutput"></div>
</div>
<div class="section">
<h3>带print输出</h3>
<button onclick="runPrint()">执行带print的代码</button>
<div class="output" id="printOutput"></div>
</div>
<div class="section">
<h3>使用numpy库</h3>
<button onclick="runNumpy()">执行numpy计算</button>
<div class="output" id="numpyOutput"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js"></script>
<script>
let pyodideInstance = null;
// 初始化Pyodide
async function initPyodide() {
if (!pyodideInstance) {
pyodideInstance = await loadPyodide();
}
return pyodideInstance;
}
async function runBasic() {
let pyodide = await initPyodide();
let code = `2 ** 10`;
let result = pyodide.runPython(code);
document.getElementById("basicOutput").innerText = "2的10次方结果:" + result;
}
async function runPrint() {
let pyodide = await initPyodide();
let outputList = [];
pyodide.setStdout({
write: (text) => { outputList.push(text); }
});
let code = `
print("这是Python的print输出")
print("100以内偶数之和:", sum(range(0, 101, 2)))
`;
pyodide.runPython(code);
document.getElementById("printOutput").innerText = outputList.join("");
}
async function runNumpy() {
let pyodide = await initPyodide();
await pyodide.loadPackage("numpy");
let code = `
import numpy as np
arr = np.arange(1, 11)
sum_val = np.sum(arr)
sum_val
`;
let result = pyodide.runPython(code);
document.getElementById("numpyOutput").innerText = "1到10的和:" + result;
}
</script>
</body>
</html>
PythonPyodideWebAssembly前端运行Python修改时间:2026-06-14 04:52:02