使用 PyScript 和 Pandas 创建交互式 Web 应用程序
PyScript 是 Web 应用程序的未来吗?也许,但可能还没有——它仍然只是一个 alpha 版本,还有很多工作要做,我敢肯定。
但是现在有多大用处呢?
我们将创建一个交互式 Web 应用程序,其中的逻辑完全用 Python 编写。
你可能听说过 PyScript,它是由 Anaconda 的 CEO Peter Wang 在 2022 年的 PyCon 大会上宣布的。还有它自己的字它是“一种闪亮的新技术......它允许用户在浏览器中编写 Python,实际上是许多语言”。
PyScript 的一大优势是您可以在不需要服务器的情况下用 Python 编写 Web 应用程序。这是通过使用 WebAssembly 编写的 Pyodide Python 解释器来实现的,WebAssembly 是现代浏览器支持的 Web 的低级语言。
到目前为止,Python Web 应用程序一直是基于服务器的,并使用 Django 或 Flask 等框架,其中前端是用 HTML 和 Javascript 创建的,而后端是在远程服务器上运行的 Python。
最近,Dash 和 Streamlit 试图通过提供纯 Python 框架来简化构建此类应用程序,从而避免学习 HTML 和 Javascript。但这些仍然是基于服务器的应用程序。
PyScript 有不同的方法。在 PyScript 中,用户界面仍然是用 HTML 构建的,但 Javascript 被 Python 取代(尽管您仍然可以使用 Javascript,如果您愿意,并且用两种脚本语言编写的函数可以相互通信)。
Web 应用程序
我将运行一个用 PyScript 和 HTML 编写的简单应用程序,它从远程源读取数据并显示一个简单的仪表板,用户可以在其中选择要在 Pandas 图表中显示的数据。
该应用程序的基本形式如下所示:
<html>
<head>
<link rel="stylesheet"
href="https://pyscript.net/alpha/pyscript.css" />
<script defer
src="https://pyscript.net/alpha/pyscript.js">
</script>
<py-env>
- libraries-that-will-be-used
</py-env>
</head>
<body>
<!-- HTML layout code goes here -->
<py-script>
# PyScript code goes here
</py-script>
</body>
</html>
如您所见,它看起来类似于标准的 HTML 文件,确实是一个。但是对于 PyScript 应用程序,我们需要在<head>
部分中包含指向 PyScript 样式表和 Javascript 库的链接,以及我们稍后将看到的<py-env>
块。
在<body>
中,我们有 HTML 布局内容,然后是包含 Python 代码的<py-script>...</py-script>
标记。
我们现在将充实这些部分。
首先,我将使用 Bootstrap 框架使整个应用程序看起来不错。这意味着我们需要包含指向 Bootstrap css 文件的链接。我们将使用 Matplotlib 和 Pandas 库,这些库需要在<py-env>...</pt-env>
部分中声明。<head>...</head>
现在看起来像这样:
<head>
<link rel="stylesheet"
href="https://pyscript.net/alpha/pyscript.css" />
<script defer
src="https://pyscript.net/alpha/pyscript.js">
</script>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<py-env>
- matplotlib
- pandas
</py-env>
</head>
接下来要看的是网页的 HTML 代码。第一部分基本上是页面的标题。我们使用 Bootstrap 中的 Jumbotron 容器。这为我们提供了一个令人愉悦的灰色背景框和一些经典 Bootstrap 风格的介绍性文字。
<div class="jumbotron">
<h1>Weather Data</h1>
<p class="lead">
Some graphs about the weather in London in 2020
</p>
</div>
在此之后有两行:第一行有一个按钮和一个下拉菜单,第二行将包含要显示的图表。
这是第一行:
<div class="row">
<div class="col-sm-2 p-2 ml-4 mb-1">
<button type="button" class="btn btn-secondary">Select chart from list:
</button>
</div>
<div class="col-sm-4 p-2 mr-4 mb-1">
<select class="form-control" id="select">
<option value="Tmax">Maximum Temperature</option>
<option value="Tmin">Minimum Temperature</option>
<option value="Sun">Sun</option>
<option value="Rain">Rain</option>
</select>
</div>
</div>
它包含两列,一列用于按钮,第二列用于菜单(我在这里使用按钮只是为了美观,它实际上并不能用作按钮)。下拉列表中的选项将用于显示四种不同图表之一。将使用的数据是 2020 年伦敦[1] 的天气状况表。表中有 12 行表示每个月,表中的列表示该月的_最高温度_,最低温度温度,太阳小时数_和_雨量_以毫米为单位。
因此,菜单项代表这些选项,并将采用“Tmax”、“Tmin”、“Sun”或“Rain”的值。
到目前为止,我们已经编写了网页代码,现在我们需要定义对用户输入做出反应并绘制图表的逻辑。这在<py-script>
部分中定义。我们接下来要处理的代码在本节中。
首先导入一些库。
# Import libraries
import pandas as pd
import matplotlib.pyplot as plt
当然,Pandas 和 Matplotlib,但我们还需要以下内容:
from pyodide.http import open_url
这是 PyScript 提供的一个库,它允许我们从网络上的源代码中读取数据,我们可以这样使用它:
url = 'https://raw.githubusercontent.com/alanjones2/uk-historical-weather/main/data/Heathrow.csv'
url_content = open_url(url)
df = pd.read_csv(url_content)
PyScript 实现的 Pandas 函数read_csv
无法直接打开 url,所以我们必须使用上面的技术。
正在下载的文件包含数十年的数据,但为了简单起见,我们将对其进行过滤以仅保存 2020 年的数据。
# filter the data for the year 2020
df = df[df['Year']==2020]
现在是在我们之前看到的 HTMLdiv
中绘制图表的函数。
# Function to plot the chart
def plot(chart):
fig, ax = plt.subplots()
df.plot(y=chart, x='Month', figsize=(8,4),ax=ax)
pyscript.write("chart1",fig)
这是用 Pandas 绘制的非常标准的东西。与“普通”Python 程序的主要区别在于它的呈现方式。pyscript.write
函数获取一个 HTML 元素的 id 并将第二个参数的内容写入其中。
这依赖于 PyScript 实现,其中包括一种呈现特定对象的方式——在本例中为 matplotlib 图表——这不一定适用于任何类型的对象。例如,如果我们想要显示一个 Plotly 图表,我们将不得不使用不同的技术,因为渲染 Plotly 图形还没有直接在 PyScript 中实现(目前)。
接下来要做的是定义一种在用户从下拉菜单中选择新图表时调用plot
函数的方式。
首先是一些更多的库——这些是作为 PyScript 的一部分提供的。
from js import document
from pyodide import create_proxy
js
库允许 PyScript 访问 Javascript 函数,在这种特殊情况下,我们正在导入访问 DOM 的能力。而来自 Pyodide 的“create_proxy\”则相反,它允许 Javascript 直接调用 PyScript 函数。
def selectChange(event):
choice = document.getElementById("select").value
plot(choice)
当发生更改事件时调用此函数。它读取选择的值,然后使用该值调用先前定义的plot
函数。
接下来我们定义一个代理,它允许更改事件调用 PyScript 函数selectChange
。
# set the proxy
def setup():
# Create a JsProxy for the callback function
change_proxy = create_proxy(selectChange)
e = document.getElementById("select")
e.addEventListener("change", change_proxy)
最后,当页面首次加载时,我们需要调用setup
函数并使用默认值 ('Tmax') 运行plot
函数,以便在启动时显示图表。
这就是实现一个简单仪表板应用程序的完整代码,就像文章开头的屏幕截图中的那个一样。此代码和演示应用程序的链接将在最后的链接中。
PyScript 与现有的基于服务器的应用程序相比如何?
就难度而言,只要你熟悉 Python,构建 Web 应用程序相对简单,可能比构建 Django 或 Flask 应用程序更容易——我建议更接近 Dash 的水平。
不过,Streamlit 是另一回事。 Streamlit 在视觉设计方面受到更多限制,但具有您不必学习 HTML 的优势。 Streamlit 应用程序非常容易创建 - 我会说比 PyScript 更容易。
然而,PyScript 相对于所有竞争对手的优势在于它不依赖服务器。这使得部署变得非常容易——我只是将您在此处看到的应用程序上传到了 Github Pages 站点,它就可以正常工作。
目前 PyScript 有点慢。由于所有工作都在浏览器中完成,性能取决于运行浏览器的机器 - 如果您的硬件较弱,那么加载您的应用程序可能需要很长时间,尽管一旦启动并运行性能似乎没事。
不过,随着硬件变得更强大、PyScript 成熟并且(希望)变得更高效,性能只会变得更好。有一天,谁知道呢,也许我们会看到 PyScript 以与今天的 Javascript 相同的方式内置到浏览器中。
您可以在我的网站上找到代码和演示网页的链接。
笔记
- 天气数据来自我的 repouk-historical-weather并且来自英国气象局Historic Station Data。它按照UK Open Government License分发,可以在相同条件下使用。
更多推荐
所有评论(0)