网络浏览器中运行Python脚本PyScript剖析
作者:DebugUsery 发布时间:2022-05-10 11:27:54
PyScript可以让你在浏览器中直接运行Python脚本,与JavaScript并排,在你的代码和网页之间进行双向互动。
由Anaconda创建的PyScript是一项实验性的但很有前途的新技术,它使Python运行时在支持WebAssembly的浏览器中作为一种脚本语言使用。
每个现代常用的浏览器现在都支持WebAssembly,这是许多语言(如C、C++和Rust)可以编译的高速运行时标准。Python的参考实现是用C语言编写的,一个早期项目Pyodide提供了Python运行时的WebAssembly移植。
也在InfoWorld上:WebAssembly的崛起
不过,PyScript的目标是提供一个完整的浏览器环境,将Python作为一种网络脚本语言运行。它建立在Pyodide之上,但增加或加强了一些功能,如从标准库中导入模块、使用第三方导入、配置与文档对象模型(DOM)的双向交互,以及做许多其他在Python和JavaScript世界中有用的事情。
现在,PyScript仍然是一个原型和实验性项目。Anaconda 并不推荐在生产中使用它。但好奇的用户可以在PyScript网站上尝试一些例子,并使用可用的组件在浏览器中构建实验性的Python+JavaScript应用程序。
在这篇文章中,我们将参观一下PyScript的基础知识,看看它是如何让Python和JavaScript进行交互的。
使用PyScript编程
PyScript的核心是一个单一的JavaScript include,你可以将其添加到网页中。这个 include 加载了基本的 PyScript 运行时间,并自动添加了对 PyScript 中使用的自定义标签的支持。
下面是一个PyScript的 "hello, world "项目的简单例子。
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" rel="external nofollow" rel="external nofollow" />
<script defer src="https://pyscript.net/unstable/pyscript.js"></script>
</head>
<body>
<py-script output="out">
print("Hello world")
</py-script>
<div id="out"></div>
</body>
</html>
head
文档中的script
标签加载了PyScript的核心功能。pyscript.css
样式表是可选的,但很有用。在其他方面,它在页面加载时向用户插入了关于页面正在做什么的通知--加载Python运行时,初始化,等等。
Python代码被包含在自定义的py-script
标签中。请注意,代码应该按照Python的缩进惯例进行格式化,否则将无法正常运行。如果你使用的编辑器能自动重新格式化HTML,请注意这一点;它可能会弄乱py-script
块的内容,使其无法运行。
一旦PyScript组件加载完毕,任何Python代码都会被评估。如果标签中的脚本写到stdout
(如print
) 语句中,你可以通过提供一个output
属性来指示在页面的什么地方显示输出。在这个例子中,脚本的stdout
被引导到ID为"out"
的div
。
如果你把它保存到一个文件中,并在网络浏览器中打开它,你会首先看到一个 "加载 "指示器和一个暂停,因为浏览器获得了PyScript的运行时间并将其设置好。该运行时在未来的加载中应保持缓存,但仍需要一些时间来激活。之后,Hello world
应该出现在页面上。
标准库导入
仅仅使用Python的内建程序的脚本只有一点用处。Python 的标准库在 PyScript 中可用,就像你在常规 Python 中使用它一样:只需import
并开始工作。标准库的导入在PyScript中应该只是工作。
如果你想修改上面的脚本块来显示当前的时间,你不需要用与传统Python不同的方法。
import datetime
print ("Current date and time:", datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S"))
使用来自PyPI的库
如果我们想从PyPI中安装一个包并使用它呢?PyScript 有另一个标签,py-env
,它指定了需要安装的第三方软件包。让我们用这两个块来替换原始脚本中的py-script
块。
<py-env>
- humanize
</py-env>
<py-script output="out">
from datetime import datetime
import humanize
now_int = int(datetime.timestamp(datetime.now()))
now_fmt = humanize.intcomma(now_int)
print("It has been", now_fmt, "seconds since the epoch.")
</py-script>
py-env
块让我们列出要添加的软件包,就像我们在 Python 项目的requirements.txt
文件中列出它们一样。然后我们可以像对待其他 Python 软件包一样导入和使用它们。在这个例子中,我们使用了一个名为humanize
的第三方软件包,以使数字输出更容易阅读。
注意,并不是所有来自PyPI的包都能按预期安装和运行。例如,requests
需要访问尚不支持的网络组件。(这个问题的一个可能的解决方法是使用pyodide.http.pyfetch
,它被原生支持)。但是纯 Python 包,如humanize
,应该运行良好。Anaconda 提供的例子中使用的包,如numpy
,pandas
,bokeh
, 或matplotlib
,也可以运行。
本地导入
对于另一种常见的情况,假设你想从与你的网页在同一目录树下的其它 Python 脚本中导入。使用导入可以更容易地将更多的 Python 逻辑从网页本身移出,在那里它和你的演示文稿混在一起,可能会变得难以处理。
通常,Python 使用文件系统中其他.py
文件的存在作为它可以导入的指示。PyScript 不能以这种方式工作,所以你需要指定哪些文件可以作为可导入模块。
比方说,你有一个名为index.html
的网页,在你的 web 服务器的某个目录下,你想在它旁边放置一个名为main.py
的 Python 文件。这样,你的页内脚本就可以只是import main
,而你可以把大部分的 Python 逻辑限制在实际的.py
文件中。
在你的py-env
块中指定你想导入的 Python 文件。
- paths:`` - ./main.py
这将允许main.py
,在与网页本身相同的 web 服务器目录下,可以与import main
一起导入。
要记住一件重要的事情。你不能对你在浏览器中本地启动的网页进行这样的导入。这是由于WebAssembly运行时和浏览器本身对文件系统访问的限制造成的。相反,你需要在网络服务器上托管这些网页,以提供网页和.py
文件。
[也在InfoWorld上:在2022年编写现代Python的4个关键]
REPL 标签
Python用户应该熟悉Jupyter Notebook,它是Python的浏览器内实时编码环境,通常用于数学和统计学。PyScript为这样的环境提供了一个原始的构建模块,即py-repl
标签。
py-repl
在网页上生成一个输入字段,其功能就像一个非常基本的Jupyter笔记本环境。下面是一个来自Anaconda自己演示的例子。
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" rel="external nofollow" rel="external nofollow" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<h1><b>pyscript REPL</b></h1>
Tip: press Shift-ENTER to evaluate a cell
<div>
<py-repl id="my-repl" auto-generate="true"> </py-repl>
</div>
</body>
</html>
运行这段代码,你会看到一个输入字段,它的工作原理类似于Python的REPL。
目前,REPL标签很少有记录的自定义方式。例如,如果你想以编程方式访问一个单元格的内容或其结果,没有明确的文档说明如何做到这一点。
IDG
PyScript的类似Jupyter的REPL组件可以让你在页面中交互式地运行Python,尽管它还不是很灵活或可配置。
与 JavaScript 事件 * 互动
因为 PyScript 是基于pyodide
的,所以它使用pyodide
的机制来与 DOM 交互。例如,如果我们想获得一个网页上的输入框的值并在我们的Python代码中使用它,我们会这样做。
<input id="txt">
<py-script>
from js import document, console
from pyodide import create_proxy
def _eventlog(e):
console.log(f"Input value: {e.target.value}")
eventlog = create_proxy(_eventlog)
document.getElementById("txt").addEventListener("input", eventlog)
</py-script>
js
库为许多常见的 JavaScript 实体提供了一个 Python 接口,比如document
和console
对象。它们在PyScript中的行为与在JavaScript中的行为几乎完全相同。pyodide
中的create_proxy
函数可以让我们取一个 Python 函数对象并为它生成一个 JavaScript 接口,因此它可以被用作input
框的事件 * 。input
框中的任何按键都会被记录到控制台,但它们也可以在Python端被处理。
来源:https://juejin.cn/post/7126527885812334623


猜你喜欢
- 本文实例讲述了PHP5.6读写excel表格文件操作。分享给大家供大家参考,具体如下:测试环境:php5.6.24.这块没啥兼容问题。需要更
- 复习回顾我们已经对Python内置模块-time中知道时间格式目前有三种。时间戳结构化时间字符串时间本期,我们将继续深入对time模块中所涉
- 一个简单的车牌输入组件(vue),供大家参考,具体内容如下代码:vue代码:<template> &l
- 后台服务在运行时发现一个问题,运行约15分钟后,接口请求报错pymysql.err.InterfaceError: (0, '
- 遇到一个很实际的问题:由于不想增加目录的深度,减少磁盘寻址的时间,需要减少一些目录层级。大家都知道建立文件夹是为了让文件管理更加的方便,现在
- 1.前言面向对象编程的三大特性:封装、继承、多态。可见继承是面向对象程序设计中一个重要的概念。Go 作为面向对象的编程语言,自然也支持继承。
- Keyboard Scan Codes (Numerical Order)Keyboard Scan Codes (Numeri
- 让左模糊查询也能走索引测试表USER_INFO表数据以及结构如下有一个USER_NAME字段的索引有个业务需求,需要模糊搜索出用户名后几位有
- 1.参数propsprops是一个对象,包含父组件传递给子组件的所有数据。在子组件中使用props进行接收。包含配置声明并传入的所有的属性的
- 1.下载PyQt官方网站:http://www.riverbankcomputing.com/software/pyqt/download5
- 本文实例讲述了python访问mysql数据库的实现方法。分享给大家供大家参考,具体如下:首先安装与Python版本匹配的MySQLdb示例
- 先声明一下,这是本人在某个项目中用到的,本人自己写的,如有雷同纯属巧合。同时也欢迎高人指正。这种星级的投票效果很常见,但是目前线上大多都是通
- 废话不多说了,直接给大家贴代码了,具体代码如下所示:-- 开窗函数:在结果集的基础上进一步处理(聚合操作)-- Over函数,添加一个字段显
- 晚上突然间看到大猫的头像在闪动,速度打开一看,发现他问,以前我写button标签的时候有没有写type属性,老实的我只有诚实地告诉他,我没写
- Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。中间件的设计为开
- 区别1let和var用来声明变量,const用来声明常量。变量就是赋值后可以改变它的值,常量就是赋值后就不能改变它的值。当声明为对象时,可以
- string iconv ( string $in_charset , string $out_charset , string $str
- 关联规则挖掘(Association rule mining)是数据挖掘中最活跃的研究方法之一,可以用来发现事情之间的联系,最早是为了发现超
- Jupyter Notebook 的快捷键使用前需要进行安装:pip install jupyter (前提是你已经安装好Python,并将
- 偶尔会在python中看见这样一行代码:data = [x**2 for x in range(0, 5)]# 此时data = [0, 1