长期以来,JavaScript一直是前端开发的主导语言,因为它能够在浏览器中原生运行,并通过DOM API与HTML和CSS交互。随着WebAssembly的出现,情况开始慢慢改变。Go、Rust、C、C++等语言现在可以以接近原生的速度在浏览器中运行,而Python也没有被落下。
随着PyScript的引入,前端开发者现在可以用Python构建丰富的前端。此外,他们还可以利用Python生态系统,其中有一些有用的科学模块,如NumPy、Matplotlib和其他许多模块。
前提条件
要获得本教程的大部分内容,你将需要
- 对HTML、CSS和JavaScript有基本了解
- 熟悉Python语法
- 一个网络服务器。我们将使用Python创建一个简单的服务器,所以请确保你的系统中安装了Python。
- 一个网络浏览器;PyScript 文档目前推荐使用 Chrome 浏览器。
什么是PyScript?
PyScript 是一个开源的网络框架,允许你使用 Python 创建前端网络应用。通过 PyScript,您可以在 HTML 中嵌入 Python 代码,或者链接到一个 Python 文件,代码将在浏览器中执行 - 而无需在后端运行 Python。
PyScript由Anaconda创建,于4月30日在2022年美国PyCon大会上公开发布。在撰写本文时,PyScript处于alpha状态,正在积极开发中,因此,由于它还没有稳定地发布,所以可以预期会有一些突破性的变化和更新的功能。
PyScript是如何工作的?
PyScript建立在Pyodide之上,它将CPython移植到WebAssembly。WebAssembly是一种低级别的二进制格式,允许你用其他语言编写程序,然后在浏览器中执行。有了WebAssembly中的CPython,我们可以在浏览器中安装和运行Python包,而PyScript则抽象了大部分Pyodide操作,让你专注于在浏览器中用Python构建前端应用程序。
为PyScript设置你的项目文件夹
在我们开始使用PyScript之前,让我们创建一个存放代码的目录。
要做到这一点,打开你的终端,使用mkdir
命令在你选择的位置创建项目目录。
mkdir pyscript_demo
接下来,使用cd
命令移动到你刚刚创建的目录中。
cd pyscript_demo
禁用自动格式化工具,如Prettier
通常,前端开发人员在他们的文本编辑器中使用自动格式化工具(如Prettier)来在保存时格式化代码。虽然这对HTML、CSS和JavaScript很有效,但在Python代码中会引起问题,因为Python对缩进很严格。
目前,像Prettier这样的自动格式化工具不能识别PyScript的语法,在写这篇文章时,PyScript才刚刚诞生两个月。这些工具将Python代码自动格式化为JavaScript,这就破坏了代码的缩进。为了补救这个问题,我们将暂时禁用这个目录的自动格式化功能。
假设你使用的是VSCode,我们可以按以下方法禁用自动格式化。
在你的项目目录中,创建一个.vscode
目录,用以下命令导航到该目录。
mkdir .vscode && cd .vscode
接下来,创建一个settings.json
文件并添加以下内容。
{
"editor.formatOnSave": false
}
这样一来,这个目录的保存时自动格式化功能在VSCode中已经被禁用,我们现在可以开始使用PyScript了。
开始使用
现在我们的目录已经为PyScript设置好了,我们将首先在HTML页面的<head>
部分添加PyScript资产的链接,其中包括一个CSS文件和JavaScript文件。
一旦添加了资产,你就可以通过两种方式在HTML文件中使用PyScript:
- 内部PyScript。你可以在HTML文件的
<py-script>
标签中编写并放置你的Python代码。<py-script>
标签可以被添加到<head>
或<body>
标签中,这取决于你手头的任务。 - 外部PyScript。这是在一个以
.py
为结尾的文件中编写Python代码,然后可以在<py-script>
标签中使用src
属性来引用该文件。
内部PyScript
开始使用PyScript的最简单、最快的方法是将Python代码嵌入到HTML文件中。让我们这样做吧!
打开你喜欢的文本编辑器,创建hello-world.html
文件并添加以下内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Hello World!</title>
<!-- linking to PyScript assets -->
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<!-- Put Python code inside the the <py-script> tag -->
<py-script>print("Hello World!")</py-script>
</body>
</html>
在<head>
部分,我们链接到pyscript.css
文件,其中包含 PyScript 视觉组件、REPL、PyScript 载入器等的样式。之后,我们链接到pyscript.js
文件,该文件设置了使用PyScript的必要功能,比如创建像<py-script>
这样的标签,你可以在那里写你的Python代码。
在<body>
标签中,你将Python代码嵌入到<py-script>
标签中。我们现在要保持简单,所以我们只是向用户打印Hello World
。
确保将你的文件保存在项目目录的根部,并在Chrome浏览器中打开hello-world.html
。它将需要几秒钟的时间来加载,一旦页面加载完毕,它将看起来类似于这样:
外部PyScript
虽然把Python代码放在<py-script>
标签中也可以,但一个更好、更可扩展的方法是把代码添加到一个外部文件中,当你创建更多的HTML页面或你的脚本变大时,在HTML文件中引用它。
以下是你应该考虑在外部文件中使用PyScript代码的一些原因。
- 该文件可以被浏览器缓存,从而带来更快的性能
- 你可以在多个页面中引用该文件,减少重复。
- 你的Python代码可以用black或Python linters等工具进行格式化。这些工具目前对嵌入 HTML 文件的 Python 代码不起作用。
为了在外部使用 PyScript,我们将创建一个index.html
文件,一个以.py
结尾的 Python 文件,其中包含我们的 Python 代码,最后在index.html
文件中引用该 Python 文件。
创建index.html
文件
创建一个index.html
文件并链接到 PyScript 资产。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Greetings!</title>
<!-- linking to PyScript assets -->
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
</body>
</html>
这个文件并没有做什么;我们只是链接到PyScript资源。为了使它更有用,我们将创建一个main.py
文件,我们的Python代码将存放在这里。
创建main.py
文件
让我们创建一个Python函数,打印一条问候信息。
在你的文本编辑器中,创建main.py
文件并添加下面的代码。
def greetings(name):
print(f'Hi, {name}')
greetings('John Doe')
greetings()
函数接收一个name
参数,并打印一个带有存储在name
参数中的名称的问候信息。当我们用John Doe
作为参数调用greetings()
函数时,它打印出hi, John Doe
。
在HTML文件中链接main.py
文件
现在你已经创建了 Python 代码,你将在index.html
文件中引用main.py
文件。
打开index.html
并在<body>
标签内添加这一行。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Greetings!</title>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
// add the following line
<py-script src="./main.py"></py-script>
</body>
</html>
<py-script>
标签有一个src
标签,它接受 Python 文件的文件路径。
在浏览器中打开index.html
文件
现在一切准备就绪,我们将在浏览器中打开index.html
。
然而,由于跨源资源共享(CORS)策略错误,浏览器将拒绝加载和执行外部Python文件。为了解决这个问题,我们将需要使用一个服务器。好在 Python 带来了一个我们可以使用的 web 服务器!这个服务器不需要由 Python 创建,你可以使用live-server或你选择的任何服务器。
要创建一个服务器,在你项目的根目录下打开终端,运行下面的命令。
python -m http.server
接下来,打开Chrome浏览器并访问 [http://0.0.0.0:8000/](http://0.0.0.0:8000/)
.服务器将自动加载index.html
文件,你将看到以下内容。
在本教程的其余部分,我们将引用一个外部 Python 文件,这需要我们使用一个服务器来避免 CORS 错误,有时为了简洁起见,我们会在 HTML 中嵌入 Python 代码。
使用PyScript REPL
PyScript 自带了一个读-评-印循环 (REPL),你可以用它来实验和尝试 Python 代码。
要使用 REPL,在你的index.html
文件中的<body>
标签中添加<py-repl>
标签。
<!DOCTYPE html>
...
<body>
<py-script src="./main.py"></py-script>
// add the following tag
<py-repl></py-repl>
</body>
</html>
在服务器仍然运行的情况下,访问 [http://0.0.0.0:8000/](http://0.0.0.0:8000/)
.你会看到一个新的部分,你可以在那里输入Python代码。
你可以导入模块,评估表达式,创建函数,以及做更多的事情。要看一个表达式的评估结果,你需要点击绿色的播放图标。
下图显示了你可以做的一些操作:
现在我们已经知道如何使用 REPL,接下来我们将学习如何在 PyScript 中创建和使用模块。
在 PyScript 中使用 Python 模块
在本节中,我们将创建一个自定义的 Python 模块并在我们的代码中使用它。我们还将使用来自 Python 标准库的模块,以及第三方模块。
为了使用模块,我们将引入一个新标签,<py-env>
,它允许我们引用模块或模块文件路径。
创建自定义模块
让我们创建一个包含两个函数的本地模块。
在你的项目目录下创建一个mathslib.py
文件,并添加以下代码。
def add(num1, num2):
return num1 + num2
def subtract(num1, num2):
return num1 - num2
这里我们创建了两个函数,做加法和减法运算。
接下来,创建一个modules.html
文件并添加以下内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>local modules</title>
<!-- linking to PyScript assets -->
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<py-env>
- paths:
- mathslib.py
</py-env>
<py-script>
from mathslib import subtract
print(subtract(8, 4))
<py-script>
</body>
</html>
在<body>
标签中,我们使用<py-env>
标签,它接受一个以paths
为键的YAML列表。mathslib.py
是相对于modules.html
文件的自定义模块的文件路径。一旦指定了自定义模块的路径,PyScript将导入文件中的模块。
装入模块后,在<py-script>
标签中,我们从mathslib.py
导入subtract()
函数,并用参数8
和4
调用该函数。
在服务器运行的情况下,访问 [http://0.0.0.0:8000/modules.html](http://0.0.0.0:8000/modules.html)
你会看到一个与此类似的页面。
从 Python 标准库中导入模块
PyScript,在Pyodide的帮助下,提供了对Python标准库中大量可用模块的访问,这些模块可以随时使用,但以下模块除外。
- tkinter
- venv
- dbm
请访问Pyodide文档以查看一个全面的列表。另外,注意那些已经包含但没有功能的模块,如多处理、线程和套接字模块。
标准库中的模块在PyScript命名空间中是默认可用的;你只需要导入它们就可以在文件中使用它们。
还是在modules.html
文件中,修改<py-script>
标签中的 Python 代码,使用random
模块生成一个随机数。
from mathslib import subtract
import random
print(subtract(8, 4))
print("random number generated: ")
print(random.randint(1, 12))
现在访问 [http://0.0.0.0:8000/modules.html](http://0.0.0.0:8000/modules.html)
页面,你会看到每次刷新页面时都会生成一个随机数。
使用第三方软件包
除了使用内置的Python模块,你还可以使用Pyodide中运来的第三方库,比如:
关于支持的第三方软件包的完整列表,请访问Pyodide文档或密切关注PyodideGitHub repo。
要添加一个第三方软件包,请创建一个新的HTML文件,third-party.html
,并添加以下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>local modules</title>
<!-- linking to PyScript assets -->
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<!-- thirdparty dependencies added here -->
<py-env>
- numpy
- matplotlib
</py-env>
<py-script>
import numpy as np
import matplotlib.pyplot as plt
arr = np.array([1, 2, 3, 4, 5])
plt.plot(arr)
plt
<py-script>
</body>
</html>
在<py-env>
标签中,我们添加一个我们想在项目中使用的第三方包的列表,这些包是NumPy和Matplotlib包。接下来,在<py-script>
标签中,我们将NumPy导入为np
,Matplotlib导入为plt
。之后,我们调用NumPy的array
方法,该方法会创建一个数组,然后存储在arr
变量中。之后,我们以数组arr
为参数,调用Matplotlib的plot
方法来绘制图形。
确保你的文件被保存,然后访问 [http://0.0.0.0:8000/third-party.html](http://0.0.0.0:8000/third-party.html)
页面。你应该看到一个类似于以下的图表。
现在你已经了解了如何使用自定义的、内置的模块和第三方软件包,我们将在下一节中学习如何访问和操作HTML元素。
使用PyScript访问和操作HTML元素
在本节中,我们将学习如何使用ID或CSS类来选择一个HTML元素,修改一个元素,将事件附加到一个元素上,并使用PyScript创建新的元素。
使用Element
类
PyScript提供了Element
类,它允许你使用其ID来选择一个HTML元素。
为了了解它是如何工作的,请创建一个elements.html
文件并插入以下内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Element class</title>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<ul id="navigation">
<li class="home">home</li>
<li class="about">about</li>
<li class="services">services</li>
<li class="contact">contact</li></ul>
</div>
<div id="output"></div>
<py-script src="./access-elements.py"></py-script>
</body>
</html>
在<body>
标签中,我们有一个ID为navigation
的<ul>
元素。我们将使用ID,用Element
类来选择这个元素。被选中的实例将给我们提供一些方法,我们可以用这些方法来选择后代并对其进行操作。
我们将使用的另一个标签是ID为output
的<div>
。我们将修改其innerHTML
,以写入一个新值。最后,在<div>
标签之后,我们链接到access-elements.py
文件,该文件将包含我们的 Python 代码。它还不存在,所以让我们继续创建它。
一旦你创建了access-elements.py
文件,就把下面的代码添加到它里面:
ul_element = Element("navigation")
first_element = ul_element.select('.home').add_class('first')
second_element = ul_element.select('.about').remove_class('about')
div_element = Element("output")
div_element.write("Value set from PyScript")
在前面的代码中,我们使用Element
类来访问使用navigation
ID 的<ul>
元素。
当使用Element
类选择一个元素时,你可以利用以下一些方法:
write()
:设置innerHTML
的值select()
:使用CSS选择器来寻找下级元素add_class()
:为一个元素添加一个或多个类remove_class()
:从一个元素中删除一个或多个类
在第二行,我们使用select()
方法来选择<ul>
元素的第一个子元素,使用它的类名home
。选择完子元素后,我们调用add_class()
方法为<li>
元素添加一个新的类first
。
在第三行,我们通过它的类名about
,访问第二个子元素,然后使用remove_class()
方法删除它的类about
。
接下来,我们调用ID为output
的Element
类,它提供了对<div>
元素的引用,该元素位于elements.html
文件中的ul
元素之后。最后,我们用字符串Value set from PyScript
调用write()
方法。该方法将把<div>
元素innerHTML
的值设置为字符串参数。
在服务器仍在运行的情况下,访问 [http://0.0.0.0:8000/elements.html](http://0.0.0.0:8000/elements.html)
并检查<ul>
元素。你会看到第一个<li>
元素现在有一个额外的类 (first
),第二个元素没有类,而div
元素现在有我们在 Python 中设置的文本。
将事件附加到元素上
我们现在可以选择HTML元素并做一些基本的操作。在这一节中,我们将给元素附加一个点击事件,并在元素被点击时让 Python 代码执行。
创建一个events.html
文件,并编写下面的代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Adding Events</title>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<button id="click-btn" class="bg-blue-500 text-white" pys-onClick="handle_click">Click</button>
<div id="output"></div>
<py-script src="./event-handlers.py"></py-script>
</body>
</html>
在<body>
标签中,我们有一个<button>
,其中有一个class
属性,包含一些属于pyscript.css
文件的类。<button>
标签也有一个pys-onclick
属性,它为按钮附加了一个click
事件。pys-onclick
属性接受函数名称handle_click
,这将是按钮被点击时运行的函数。
接下来,我们有一个ID为output
的div
元素。我们将用我们定义的handle_click
函数修改innerHTML
中的元素。
最后,我们链接到event-handlers.py
文件,该文件将包含事件处理函数。
让我们定义event-handlers.py
,并添加以下内容:
def handle_click(e):
pyscript.write("output", "you clicked the button")
handle_click
函数有一个参数,e
,这是当你点击按钮时自动传递给函数的一个事件对象。在函数内部,我们调用PyScript的write()
方法,它需要两个参数:元素IDoutput
和我们要写的值,在我们的例子中是you clicked the button
。
请确保你的服务器正在运行。
python -m http.server
然后访问URL [http://0.0.0.0:8000/events.html](http://0.0.0.0:8000/events.html)
在Chrome中。当页面加载时,点击按钮,会出现一条 "你点击了按钮 "的信息。
使用JavaScript来访问和操作DOM
PyScript提供了一个js
模块,让你可以访问JavaScript方法,如querySelector()
,createElement()
,appendChild()
等,以访问和操作HTML元素。有了这些方法,你就可以把 JavaScript 和 Python 混在一起,做一些很酷的 DOM 操作。下面是一个例子。
import js
print(js.window.innerHeight)
nav = js.document.createElement("div")
js.document.body.prepend(nav)
js.console.log("nav element created")
正如你所看到的,我们将Python代码方法(如print()
)与JavaScriptwindow
或document
属性混合在一起。
在这一节中,我们将主要关注document
方法,很方便地,PyScript使它在Python范围内自动可用。我们甚至不需要导入js
模块来使用document
方法。
创建一个dom.html
文件并添加以下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Mixing JavaScript and Python</title>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<ul id="navigation">
</ul>
<py-script src="./js-dom.py"></py-script>
</body>
</html>
在<body>
标签中,我们只有一个空的<ul>
元素,其 ID 为navigation
。接下来,我们引用js-dom.py
,它将包含我们的 Python 代码。
创建js-dom.py
文件并添加以下内容。
nav_parent = document.querySelector('#navigation')
nav_texts = ["home", "about", "services", "contact"]
for text in nav_texts:
nav_item = document.createElement("li")
nav_item.textContent = text
nav_item.className = "nav_element"
nav_parent.appendChild(nav_item)
在第一行,我们调用document
模块的querySelector()
方法,参数为#navigation
。该方法将找到并返回一个 ID 为navigation
的元素,这就是dom.html
文件中的<ul>
元素。
在第二行,我们创建一个导航文本的列表,并将其存储在nav_texts
变量中。之后,我们对nav_texts
列表进行迭代。在每次迭代中,我们用一个字符串li
来调用createElement()
方法,创建一个<li>
元素。
之后,我们使用textContent
属性向<li>
元素添加文本,并使用className
属性向<li>
元素添加一个类名nav_element
。最后,我们通过调用appendChild()
,以nav_item
作为参数,将<li>
元素附加到<ul>
元素上。
确保你的文件已被保存,服务器仍在运行。访问 [http://0.0.0.0:8000/dom.html](http://0.0.0.0:8000/dom.html)
,你会看到一个类似于以下的页面。
如果你进一步研究并检查这些元素,你会看到<li>
元素已经用类名nav_element
创建,这是我们在 Python 中设置的。
现在我们可以使用Element
类访问和操作 DOM,将事件附加到元素上,并使用 JavaScript 来查询和修改 DOM。接下来,我们将使用PyScript从一个API中获取数据。
从API中获取和渲染数据
在这一节中,我们将使用PyScript向API发送一个GET
请求来获取数据。我们将使用的API是随机数据API。我们将创建一个带有点击事件的按钮,在每次点击按钮时运行一个调用API的函数。
在你的目录中创建一个fetch_data.html
文件,并添加以下内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Fetch data from API</title>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<button id="get-name" class="bg-green-600 text-white" pys-onClick="get_random_name">Generate Random Name</button>
<div id="output"></div>
<py-script src="./fetch.py"></py-script>
</body>
</html>
这时的代码应该是熟悉的。最重要的部分是<button>
标签,它有接受get_random_name()
函数的pys-onClick
属性。该函数将驻留在底部链接的fetch.py
文件中。让我们继续创建该文件。
在你的文本编辑器中,创建一个名为fetch.py
的新文件,内容如下。
from pyodide.http import pyfetch
import asyncio
async def get_random_name(e):
response = await pyfetch(url="https://random-data-api.com/api/name/random_name", method="GET")
data = await response.json()
first_name = data.get('first_name')
middle_name = data.get('middle_name')
last_name = data.get('last_name')
output = f"Random name: {first_name} {middle_name} {last_name}"
pyscript.write('output', output)
在第一行,我们从pyodide.http
模块中导入pyfetch()
方法,它允许我们进行异步的网络请求。在第二行,我们导入asyncio
模块,它是 Python 标准库的一部分,提供了async
和await
关键字,这些关键字对于创建异步函数很有用。
接下来,我们定义一个异步函数get_random_name()
,用asyncio
模块中的async
关键字作为前缀。在这个函数中,我们调用了接受两个参数的pyfetch()
方法。
URL
:API端点method
:Species 你想使用的HTTP方法,这里是GET
方法。
当pyfetch()
运行时,它返回一个对象,然后将其存储在response
变量中。在接下来的一行中,我们在response
对象上调用json()
来解析 JSON 并返回一个 Python 字典,然后将其存储在data
变量中。
在接下来的几行中,我们从data
dict 中提取名字、中间名和姓氏,并将它们存储在各自的变量中。output
最后,我们使用Python的f-strings将名字连接起来,并调用pyscript.write()
方法,将数据写入ID为<div>
的元素中。
确保你的服务器正在运行,并访问 [http://0.0.0.0:8000/fetch_data.html](http://0.0.0.0:8000/fetch_data.html)
页面。一旦页面加载,点击Generate Random Name
按钮。你会看到,每次点击该按钮都会产生一个新的名称。
持续性地使用数据localStorage
在本节中,我们将使用本地存储来保存和检索数据。本地存储是网络浏览器中的一个对象,它可以存储没有过期日期的数据。Python 可以通过从js
模块中导入本地存储来使用它。
为了使用本地存储,我们将创建一个文本区,允许用户输入评论。如果他们想保存评论,他们将点击一个save
按钮,该按钮将运行一个函数,将数据保存在本地存储中。每次访问该页面时,数据将被从本地存储中检索出来,文本区将被设置为该数据。
创建一个storage.html
文件并添加以下内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Store data in local storage</title>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<textarea id="comment" class="block border"></textarea>
<button id="save" class="bg-green-600 text-white"
pys-onClick="save_comment">Save</button>
<py-script src="./local-storage.py"></py-script>
</body>
</html>
在<body>
标签中,我们创建一个ID为comment
的<textarea>
标签。我们将使用这个ID来获取Python中的文本区元素的引用。接下来,我们有一个按钮,它的ID是save
,还有一个点击事件,它将调用函数save_comment
,我们还没有定义。最后,我们引用local-storage.py
,它将包含我们的 Python 代码。现在我们来创建这个文件。
创建local-storage.py
并添加以下内容:
from js import localStorage
def save_comment(e):
text = Element("comment").value
localStorage.setItem("comment", text)
if localStorage.getItem("comment"):
text_area = Element("comment")
text_area.write(localStorage.getItem("comment"))
首先,我们从js
模块中导入localStorage
对象。接下来,我们定义save_comment()
函数,它以e
为参数。在该函数中,我们调用ID为comment
的Element
类,以获得一个文本区域的引用。一旦该方法找到了文本区域,我们使用value
属性来获得文本区域的内容,并将该值存储在text
变量中。在下一行,我们调用localStorage
对象的setItem()
方法,将注释文本保存在localStorage
对象的comment
键下。
现在,save_comment()
函数只有在点击save
按钮时才会运行。然而,在save_comment()
函数之外进行,该函数后面的行将只在页面加载时执行。
当页面第一次加载时,我们使用if
语句来检查localStorage
对象在comment
键下是否有数据。如果是真的,我们使用Element
类来引用文本区,并将其实例存储在text_area
变量中。接下来,我们调用text_area
实例的write()
方法,用本地存储的数据更新文本区的内容。
确保你的服务器正在运行并访问 [http://0.0.0.0:8000/storage.html](http://0.0.0.0:8000/storage.html)
.输入任何你喜欢的文本,然后点击保存按钮。
接下来,刷新URL,你会看到文本区包含你在初次访问时保存的文本。
就这样,你现在知道了如何使用PyScript来利用localStorage
。接下来,我们将使用PyScript读取文件系统中的一个文件。
与文件系统互动
在本节中,我们将使用PyScript从本地文件系统中的明文文件中读取数据,并将其内容追加到DOM中。
首先,让我们创建一个包含我们想要读取的数据的文件。在你的主项目目录下,运行下面的命令来创建并移动到一个新的目录。
mkdir data && cd data
接下来,创建一个names.txt
文件并添加以下内容,这些内容是Python网络框架的名称。
Django
Flask
FastAPI
web2p
保存该文件并回到你的项目根目录。
cd ..
创建好文件后,在你的文本编辑器中创建一个file-system.html
文件,内容如下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Read data from file system</title>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<py-env>
- paths:
- /data/names.txt
</py-env>
<ul id="frameworks">
</ul>
<py-script src="./read-file.py"></py-script>
</body>
</html>
在<py-env>
标签中,我们指定到names.txt
的路径,它是相对于file-system.html
的路径。接下来,我们创建一个空的<ul>
标签,有一个frameworks
ID。最后,我们引用read-file.py
,我们将很快定义这个标签。
创建一个具有以下内容的read-file.py
。
ul_element = document.querySelector("#frameworks")
with open("names.txt") as f:
for line in f:
li_element = document.createElement("li")
li_element.innerText = line
ul_element.appendChild(li_element)
在第一行,我们用一个ID选择器#frameworks
,调用querySelector()
方法,得到一个对<ul>
元素的引用。在第二行中,我们用文件名names.txt
来调用open()
方法,并将文件对象存储为f
。
在with
语句中,我们对存储在文件对象f
中的每一行进行迭代。在每个迭代过程中,我们使用document
对象的createElement()
方法创建一个<li>
元素。接下来,我们使用li_element
实例的innerText
属性,将<li>
的文本内容设置为line
变量中的值。最后,我们通过调用以li_element
为参数的appendChild()
,将<li>
元素附加到<ul>
元素上。
再次启动服务器(如果你之前停止了它)。
python -m http.server
访问 [http://0.0.0.0:8000/file-system.html](http://0.0.0.0:8000/file-system.html)
URL,你会看到纯文本文件的内容显示在页面上。
如果你检查这些元素,你会看到有四个<li>
元素被附加到<ul>
元素上。
有了这个,你现在可以读取文件系统中的文件了。你可以用同样的方法来读取CSV文件和其他许多文件格式。
总结
在本教程中,我们学习了如何使用 PyScript REPL,创建自定义模块,使用 Python 标准库中的模块,以及导入第三方模块。我们还学习了如何使用 PyScript 访问和操作元素,提出 API 请求,使用localStorage
,以及从文件系统中读取纯文本文件。