在网页里运行 Python

在网页里运行 Python

作者: 莫烦 编辑: 莫烦 发布于: 2022-04-02

这篇文章是一篇技术文章,我想分享在自己如何一步步搭建起来一个可以在公网访问的 Python 执行环境。并对比和其它几种经典方式的优缺点。

你可能好奇,什么是交互式代码学习。Jupyter notebook 就是一个最好的例子。他可以让你在自己的电脑上,通过编写一块一块的代码, 对每一块单独运行,并且实现块与块之间的结果缓存。这特点使得 Jupyter Notebook 广受好评。

jupyter

不过好事伴随着一些局限性,如果你是一个学习者,你使用 Notebook 的情况多半是把网页上的代码 copy 下来,然后放在本地的 Notebook 实例中运行, 你很少有见到直接在公网的站点提供 Notebook 运算单元给你免费学习使用的吧。

现实情况

说到底,对于学习服务提供商,这还是钱的事情。你可别看运行代码这件事,如果人家给你做出来一个 Notebook 服务, 意味着人家背后有很多服务器,你提交运行一行代码,实际上是在人家服务器上跑的,人家给你返回运算结果。

如果这种服务现在不收费,迟早有一天是要收费的,因为服务器和运算单元都很贵呀。莫烦是做开源的, 资源有限,肯定不会去买那么多服务器,给你免费用计算资源。 但是莫烦的理念是想降低知识传播的门槛, 我还是很想让你体验到所见即所得,所学即所感的学习状态。

my example

捣腾的结果就如上图,你可以在 莫烦Python 上直接运行 Python 代码,还不用占用我服务器的运算资源。 交互体验 demo 在这

而且,我也独立开发了 MiniPy Python 小程序模块,让你可以更轻松的看到别人是如何使用 Python 制作出丰富的小项目的。 而且支持分享和一键克隆,让你可以基于优秀的项目,做一个更优秀,更能量身定制的小程序。在外任何地方都能访问且运行。

minipyDemo

怎么办

交互式运行代码的确是一件很酷的事,那怎么才能在公网中组建一个价格友善的,既可以学又可以直接运行的平台呢? 总结起来途径就收敛到一种,不在服务器运行代码,而在浏览器中运行代码

Yasoob Khalid 的 Running Python in the Browser 这篇文章, 是我参考的主要基础。

python in browser

他总结了 6 种解决方案,各有利弊。比如有的是将你在网页上写的 Python 转化成 JavaScript 代码(浏览器可直接运行 JavaScript),然后再运行, 有的是在浏览器中加入 Python 执行器,运行纯正的 Python。 有的在浏览器加载数据前要编译好 Python 代码,有的在加载页面后编译。

Pyodide

在综合了他们所有优缺点之后,我选则了拓展性和可维护性更好的 Pyodide 方案。 简单来说,Pyodide 在你打开网页后,拿到你输入的 Python 代码, 在一个你同网页一起加载好的 Python 执行器中跑一遍,给你返回结果,一旦你的网页加载好了,你可以重复利用这个执行器一直执行代码。 简直和 Notebook 一模一样,只是一个浏览器里面的 Notebook。

pyodide

这也不是没有缺点。最明显的缺点,Python 执行器的文件很大(少则15MB,多则 50、60MB 甚至更多),光下载就要一阵子。 而且这些文件都在外国网站,国内的访问速度有限。对于我就更致命了,我比较想要大家体验到相对流畅的加载,我自建了 CDN, 这玩意儿在我全网站 CDN 流量中占90%。烧钱!

另外的缺点是他并不一定能运行像 Tensorflow 这种大型的机器学习库,如果能运行,通过 CDN 流量下载一个 400+MB 的 Tensorflow 给你, 不知道别人愿不愿意,反正我是不愿意的,我没那么多钱。目前 Pyodido 支持的 Python 库还算丰富的, 经典的 Numpy,Pandas,Matplotlib 这些都是支持的。你在 这里可以看到它目前支持的所有库

综合考量,Pyodide 还是比较适合我来做类 Notebook 的 Python 教学的。

代码编辑

光有 Pyodide 还不行,因为它只是一个执行器,而不是编辑器。你看到的这种黑底代码框其实是编辑器。

my example

没有了编辑器,你就无法自定义的在网页上写代码,编辑代码了。所以得整一个编辑器。 我的选择是经过时间考量的 CodeMirror

codemirror

把它们按照我网页上的逻辑插入到具体的位置,无论你在里面编辑什么,它的作用都是记录里面的文字,用点小工具让你感受到代码编辑器的关怀。 在这里体验一下

总的来说,这 CodeMirror 就是一个高级文本编辑器。它也不能运行代码,只能让你好好打代码,然后运行代码的工作就交给躲在浏览器后面的 Pyodide。

实践案例

我在下面简单来介绍一下,如果你想了解具体的技术的话,可以接着往下看。 在我体验网页中, Pyodide + CodeMirror 是怎么构建起来的?

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.1/codemirror.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.1/codemirror.min.js"></script>

<textarea id="myTextArea"></textarea>
<script>
  const tx = document.getElementById("myTextArea");
  var editor = CodeMirror.fromTextArea(tx, {
    lineNumbers: true,
    value: 'print("莫烦 Python")'  
  });
</script>

上面这一块就是 CodeMirror 的结构,当然,这离一个真正的,好看的代码块还差远了。不过作为 demo 足以。 下面在看看 Pyodide 怎么调用到 CodeMirror 里面的代码。

<script src="https://cdn.jsdelivr.net/pyodide/v0.19.1/full/pyodide.js"></script>
<script>
  // 拿 CodeMirror 里的代码字符串  
  const code = editor.getValue(); 
  
  // 放到 Pyodide 里执行
  async function main() {
  let pyodide = await loadPyodide({ indexURL : "https://cdn.jsdelivr.net/pyodide/v0.19.1/full/" });
    console.log(pyodide.runPython(code));
  };
  main();  
</script>

你看,最基础的逻辑就是这么简单。只要你再添加上 css 样式,就基本能用了。

总结

莫烦愿意分享新的技术和想法,做交互式学习也是处于分享的乐趣,谢谢你见证 莫烦Python 的再一次成长。


降低知识传递的门槛

莫烦经常从互联网上学习知识,开源分享的人是我学习的榜样。 他们的行为也改变了我对教育的态度: 降低知识传递的门槛免费 奉献我的所学正是受这种态度的影响。 【支持莫烦】 能让我感到认同,我也更有理由坚持下去。

如果你和莫烦一样,对知识的沉淀和"学习"这件事感兴趣,欢迎通过微信验证加群,我们用行动促进知识的传递。 (微信号:morvanzhou;请备注:"莫烦Rethink",不然无法通过验证)