我正在尝试将 Python 海龟模块与 pyodide 一起使用。这不是官方支持,但我发现了另一个StackOverflow答案,建议使用来自 Basthon 的修改版本。因此,我将 Basthon 中的文件复制到新的目录结构中:
pyodide/
turtle/
src/
turtle/
__init__.py
svg.py
pyproject.toml
我的 pyproject.toml 文件包含以下内容:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "turtle"
version = "0.0.1"
我使用以下脚本成功构建了一个轮子:
#!/bin/bash
pushd pyodide/turtle
python3 -m pip install --upgrade build
python3 -m build
popd
然后我使用以下 HTML 成功使用海龟轮加载 pyodide:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Pyodide</title>
<script src="https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js"></script>
</head>
<body>
<textarea id="input" cols="80" rows="15">
import turtle
t = turtle.Turtle()
t.forward(100)
</textarea>
<br/>
<button id="run" onclick="run()" disabled>Run</button>
<pre id="output">Loading pyodide...</pre>
<div id="visual"></div>
<script type="text/javascript">
const runButton = document.getElementById("run");
const input = document.getElementById("input");
const output = document.getElementById("output");
let pyodide;
const main = async () => {
pyodide = await loadPyodide({
stdout: (text) => output.innerHTML += text + "\n",
});
runButton.disabled = false;
output.innerHTML = "";
};
main();
const run = async () => {
output.innerHTML = "";
try {
await pyodide.loadPackage("./turtle/dist/turtle-0.0.1-py2.py3-none-any.whl");
await pyodide.loadPackagesFromImports(input.value);
await pyodide.runPython(input.value);
} catch (error) {
console.log(error);
}
};
</script>
</body>
</html>
我通过运行
python -m http.server
从 Web 服务器运行了上述 HTML。由于 CORS 浏览器限制,这允许它读取 .whl
文件。
但是,我不确定如何在网页上实际输出 SVG。我查看了 Basthon 源代码,但找不到执行此操作的方法。我能找到的最接近的是
turtle.svg()
但是当我从 python 调用它时,我在 JavaScript 控制台中收到以下错误:
TypeError:“pyodide.ffi.JsProxy”对象不可调用
我尝试阅读有关 pyodide 类型转换的内容,但不明白我需要做什么。
是否可以将绘图上下文绑定到页面上的 SVG,以便海龟实时生成动画?或者只能使用 Basthon 海龟包渲染完成的 SVG?有没有更简单的方法让 pyodide 和turtle 在浏览器窗口中处理实时图形?
我根据这个网络工作者示例找到了它我发现使用了相同的 Basthon 海龟包。这些是我在 python 中需要的附加行:
from js import document
turtle.Screen().show_scene()
document.getElementById("visual").innerHTML = turtle.svg()