我最近遇到了Pyodide项目。
我使用Pyodide构建了一个小演示,但是虽然我花了很多时间查看源代码,但对于我来说,如何将print输出从python重定向(除了修改CPython源代码之外),以及如何将输出从matplotlib.pyplot重定向到浏览器还不太明显。
从源代码来看,FigureCanvasWasm确实有一个具有适当后端的show()方法,用于绘制浏览器画布--但是,我不清楚如何实例化这个类并调用它的show()方法,或者是否还有更明显的将绘图重定向到画布的方法。
因此,我的问题是:
print()消息这是我的测试页面:
<!doctype html>
<meta charset="utf-8">
<html lang="en">
<html>
<head>
<title>Demo</title>
<script src="../../pyodide/build/pyodide.js"></script>
</head>
<body>
</body>
<script type="text/javascript">
languagePluginLoader.then(() => {
pyodide.loadPackage(['matplotlib']).then(() => {
pyodide.runPython(`
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
#fig = plt.gcf()
#fig.savefig(imgdata, format='png')
print('Done from python!')`
);
//var image = pyodide.pyimport('imgdata');
//console.log(image);
});});
</script>
<html>发布于 2019-06-19 14:48:32
首先,让我们看看是否可以在浏览器中显示任何内容;例如,一个普通的字符串。Python变量存储在pyodide.globals属性中。因此,我们可以从那里获取python对象,并将其放在页面上的<div>元素中。
<!doctype html>
<meta charset="utf-8">
<html>
<head>
<title>Demo</title>
<script src="../pyodide/pyodide.js"></script>
</head>
<body>
</body>
<script type="text/javascript">
languagePluginLoader.then(() => {
pyodide.runPython(`my_string = "This is a python string." `);
document.getElementById("textfield").innerText = pyodide.globals.my_string;
});
</script>
<div id="textfield"></div>
<html>现在,我想我们可以用matplotlib图来做同样的事情。下面将显示文档中保存的png图像。
<!doctype html>
<meta charset="utf-8">
<html lang="en">
<html>
<head>
<title>Demo</title>
<script src="../pyodide/pyodide.js"></script>
</head>
<body>
</body>
<script type="text/javascript">
languagePluginLoader.then(() => {
pyodide.loadPackage(['matplotlib']).then(() => {
pyodide.runPython(`
import matplotlib.pyplot as plt
import io, base64
fig, ax = plt.subplots()
ax.plot([1,3,2])
buf = io.BytesIO()
fig.savefig(buf, format='png')
buf.seek(0)
img_str = 'data:image/png;base64,' + base64.b64encode(buf.read()).decode('UTF-8')`
);
document.getElementById("pyplotfigure").src=pyodide.globals.img_str
});});
</script>
<div id="textfield">A matplotlib figure:</div>
<div id="pyplotdiv"><img id="pyplotfigure"/></div>
<html>我还没有研究过backends.wasm_backend,所以这可能允许更自动化的上述方法。
发布于 2020-01-02 22:48:00
在使用wasm后端时,图形的画布属性是FigureCanvasWasm的一个实例。调用画布的show()方法应该足以在浏览器中显示图形。不幸的是,画布的create_root_element()方法中的一个小错误阻止了图形的显示。此方法创建一个包含图的div元素。它首先尝试创建一个碘输出div元素。如果失败,将创建一个普通的HTML元素。然而,这个元素从未追加到文档中,因此仍然是不可见的。
如果发生这种情况,下面是来自FigureCanvasWasm的代码行
def create_root_element(self):
# Designed to be overridden by subclasses for use in contexts other
# than iodide.
try:
from js import iodide
return iodide.output.element('div')
except ImportError:
return document.createElement('div')该评论建议,非碘化物代码是一个存根,需要扩展,通过覆盖的方法。这需要子类FigureCanvasWasm,将其安装为pyodide模块,并配置matplotlib以使用该后端。
但是有一个快捷方式,因为python允许重写实例的方法,而不需要修改类,就像问题394770一样。将以下代码放入HTML文档中会给出浏览器中的一个图形
import numpy as np
from matplotlib import pyplot as plt
from js import document
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
f = plt.figure()
plt.plot(x,y)
# ordinary function to create a div
def create_root_element1(self):
div = document.createElement('div')
document.body.appendChild(div)
return div
#ordinary function to find an existing div
#you'll need to put a div with appropriate id somewhere in the document
def create_root_element2(self):
return document.getElementById('figure1')
#override create_root_element method of canvas by one of the functions above
f.canvas.create_root_element = create_root_element1.__get__(
create_root_element1, f.canvas.__class__)
f.canvas.show()最初,工具栏没有显示图标。我必须下载、解压缩和安装火锅,并在头中包含以下行以获得这些
<link rel="stylesheet" href="font-awesome-4.7.0/css/font-awesome.min.css">编辑:关于您问题的第一部分,将输出流重定向到浏览器,您可以看看在pyodide的console.html中是如何完成的。
它将sys.stdout替换为StringIO对象
pyodide.runPython(`
import sys
import io
sys.stdout = io.StringIO()
`);然后运行python代码(可以完全忽略它在wasm上下文中运行的事实)。
pyodide.runPython(`
print("Hello, world!")
`);最后,将stdout缓冲区的内容发送到输出元素。
var stdout = pyodide.runPython("sys.stdout.getvalue()")
var div = document.createElement('div');
div.innerText = stdout;
document.body.appendChild(div);发布于 2021-10-08 22:09:49
要显示print()调用form pyodide,可以使用loadPyodide上的参数重定向stdout:
var paragraph = document.getElementById("p");
pyodide = await loadPyodide({
indexURL : "https://cdn.jsdelivr.net/pyodide/v0.18.1/full/",
stdin: window.prompt,
stdout: (text) => {paragraph.textContent += text;},
stderr: (text) => {paragraph.textContent += text;}
});https://github.com/pyodide/pyodide/blob/main/src/js/pyodide.js
https://stackoverflow.com/questions/56583696
复制相似问题