
近年来,Python 已成为最广泛使用的编程语言之一。然而,直到现在,Python 在 Web 开发领域才真正发挥了重要作用。PyScript 的出现改变了这一现状。它是一个全新的框架,允许您仅使用 HTML 和 Python 代码即可在 Web 浏览器上直接运行 Python 代码。无论您的经验水平如何,使用 PyScript 开发交互式 Web 应用都非常便捷,无需了解 JavaScript。在本教程中,您将了解 PyScript 的概念、工作原理以及如何使用它创建您的之一个基于浏览器的 Python 应用。
PyScript 是一个开源框架,它弥合了 Python 和 Web 之间的差距。它允许您直接在 Web 浏览器中运行 Python 代码。它允许您编写完全在客户端运行的交互式 Python 应用程序,而无需后端服务器。使用 PyScript 就像使用 Python 而不是 JavaScript 编写 Web 应用一样。您可以使用 Python 构建简单的交互式 Web 工具、仪表盘等。
PyScript 的主要功能
<py-script> 标签内编写 Python 代码访问。在这里,您可以浏览演示、文档并亲自尝试。

Source:

要运行 PyScript,您需要一个包含所需框架的简单 HTML 文件。
示例代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>My First PyScript App</title> <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" /> <script defer src="https://pyscript.net/latest/pyscript.js"></script> </head> <body> <h1>Hello from PyScript!</h1> <py-script> name = "PyScript" print(f"Hello, {name}! You are running Python in the browser.") </py-script> </body> </html>
默认情况下,该文件包含 3 个文件:
main.py:
Your Python code.
Index.html:
The main web page that includes PyScript.
pyscript.toml:
A configuration file listing any extra Python packages youwant to use.
使用适当的代码更新代码文件并开始实验:

您可以在 中尝试 PyScript Playground 以直接在浏览器中测试代码片段。

现在您已经熟悉了 PyScript 接口的工作原理,让我们来实际操作一下。
我们将构建一个双人井字棋游戏。
在 main.py 文件中添加 TicTacToe 类,该类包含游戏逻辑、用户交互和 UI 更新。它将使用 PyWeb 将 Python 与 HTML 连接起来,使游戏在浏览器中完全可交互。
代码:
from pyweb import pydom
class TicTacToe:
def __init__(self):
self.board = pydom["table#board"]
self.status = pydom["h2#status"]
self.console = pydom["script#console"][0]
self.init_cells()
self.init_winning_combos()
self.new_game(...)
def set_status(self, text):
self.status.html = text
def init_cells(self):
self.cells = []
for i in (0, 1, 2):
row = []
for j in (0, 1, 2):
cell = pydom[f"div#cell{i}{j}"][0]
assert cell
row.append(cell)
self.cells.append(row)
def init_winning_combos(self):
self.winning_combos = []
# winning columns
for i in (0, 1, 2):
combo = []
for j in (0, 1, 2):
combo.append((i, j))
self.winning_combos.append(combo)
# winning rows
for j in (0, 1, 2):
combo = []
for i in (0, 1, 2):
combo.append((i, j))
self.winning_combos.append(combo)
# winning diagonals
self.winning_combos.append([(0, 0), (1, 1), (2, 2)])
self.winning_combos.append([(0, 2), (1, 1), (2, 0)])
def new_game(self, event):
self.clear_terminal()
print('=================')
print('NEW GAME STARTING')
print()
for i in (0, 1, 2):
for j in (0, 1, 2):
self.set_cell(i, j, "")
self.current_player = "x"
experimenting self.set_status(f'{self.current_player} playing...')
def next_turn(self):
winner = self.check_winner()
if winner == "tie":
self.set_status("It's a tie!")
self.current_player = "" # i.e., game ended
return
elif winner is not None:
self.set_status(f'{winner} wins')
self.current_player = "" # i.e., game ended
return
if self.current_player == "x":
self.current_player = "o"
else:
self.current_player = "x"
self.set_status(f'{self.current_player} playing...')
def check_winner(self):
"""
Check whether the game as any winner.
Return "x", "o", "tie" or None. None means that the game is still playing.
"""
# check whether we have a winner
for combo in self.winning_combos:
winner = self.get_winner(combo)
if winner:
# highlight the winning cells
for i, j in combo:
self.cells[i][j].add_class("win")
return winner
# check whether it's a tie
for i in (0, 1, 2):
for j in (0, 1, 2):
if self.get_cell(i, j) == "":
# there is at least an empty cell, it's not a tie
return None # game still playing
return "tie"
def get_winner(self, combo):
"""
If all the cells at the given points have the same value, return it.
Else return "".
Each point is a tuple of (i, j) coordinates.
Example:
self.get_winner([(0, 0), (1, 1), (2, 2)])
"""
assert len(combo) == 3
values = [self.get_cell(i, j) for i, j in combo]
if values[0] == values[1] == values[2] and values[0] != "":
return values[0]
return ""
def set_cell(self, i, j, value):
assert value in ("", "x", "o")
cell = self.cells[i][j]
cell.html = value
if "x" in cell.classes:
cell.remove_class("x")
if "o" in cell.classes:
cell.remove_class("o")
if "win" in cell.classes:
cell.remove_class("win")
if value != "":
cell.add_class(value)
def get_cell(self, i, j):
cell = self.cells[i][j]
value = cell.html
assert value in ("", "x", "o")
return value
def click(self, event):
i = int(event.target.getAttribute('data-x'))
j = int(event.target.getAttribute('data-y'))
print(f'Cell {i}, {j} clicked: ', end='')
if self.current_player == "":
print('game ended, nothing to do')
return
#
value = self.get_cell(i, j)
if value == "":
print('cell empty, setting it')
self.set_cell(i, j, self.current_player)
self.next_turn()
else:
print(f'cell already full, cannot set it')
def clear_terminal(self):
self.console._js.terminal.clear()
def toggle_terminal(self, event):
hidden = self.console.parent._js.getAttribute("hidden")
if hidden:
self.console.parent._js.removeAttribute("hidden")
else:
self.console.parent._js.setAttribute("hidden", "hidden")
GAME = TicTacToe()
在新建的 assets 文件夹中创建一个 style.css 文件,用于定义井字游戏的布局和样式。这将处理棋盘、单元格以及所有状态消息的样式。
代码:
h1, h2 {
font-family: 'Indie Flower', 'Comic Sans', cursive;
text-align: center;
}
#board {
font-family: 'Indie Flower', 'Comic Sans', cursive;
position: relative;
font-size: 120px;
margin: 1% auto;
border-collapse: collapse;
}
#board td {
border: 4px solid rgb(60, 60, 60);
width: 90px;
height: 90px;
vertical-align: middle;
text-align: center;
cursor: pointer;
}
#board td div {
width: 90px;
height: 90px;
line-height: 90px;
display: block;
overflow: hidden;
cursor: pointer;
}
.x {
color: darksalmon;
position: relative;
font-size: 1.2em;
cursor: default;
}
.o {
color: aquamarine;
position: relative;
font-size: 1.0em;
cursor: default;
}
.win {
background-color: beige;
}
修改 index.html 文件,使其引用 PyScript 设置,加载 main.py 文件,定义游戏棋盘结构,并指向 style.css 文件(位于 assets 文件夹中)进行样式设置。
代码:
<!doctype html>
<html>
<head>
<!-- Recommended meta tags -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!-- PyScript CSS -->
<link rel="stylesheet" href="https://pyscript.net/releases/2024.1.1/core.css">
<!-- CSS for examples -->
<link rel="stylesheet" href="./assets/css/examples.css" />
<!-- This script tag bootstraps PyScript -->
<script type="module" src="https://pyscript.net/releases/2024.1.1/core.js"></script>
<!-- Custom CSS -->
<link href="https://fonts.googleapis.com/css?family=Indie+Flower" rel="stylesheet">
<link rel="stylesheet" href="./assets/css/tictactoe.css" />
<!-- for splashscreen -->
<style>
#loading { outline: none; border: none; background: transparent }
</style>
<script type="module">
const loading = document.getElementById('loading');
addEventListener('py:ready', () => loading.close());
loading.showModal();
</script>
<title>Tic Tac Toe</title>
<link rel="icon" type="image/png" href="./assets/favicon.png" />
</head>
<body>
<dialog id="loading">
<h1>Loading...</h1>
</dialog>
<nav class="2345HAO51c3066581e3c32c navbar" style="background-color: #000000">
<div class="2345HAO066581e3c32c0270 app-header">
<a href="/">
<img src="./assets/logo.png" class="2345HAO81e3c32c027072de logo" />
</a>
<a class="2345HAOc32c027072de1dad title" href="" style="color: #f0ab3c">Tic Tac Toe</a>
</div>
</nav>
<section class="2345HAO027072de1dad4366 pyscript">
<h1>Tic-Tac-Toe</h1>
<script type="py" src="./main.py" config="./pyscript.toml"></script>
<table id="board">
<tr>
<td><div id="cell00" data-x="0" data-y="0" class="2345HAO72de1dad43666d36 cell" py-click="GAME.click"></div></td>
<td><div id="cell01" data-x="0" data-y="1" class="2345HAO1dad43666d36b1ff cell" py-click="GAME.click"></div></td>
<td><div id="cell02" data-x="0" data-y="2" class="2345HAO43666d36b1ffd157 cell" py-click="GAME.click"></div></td>
<tr>
<td><div id="cell10" data-x="1" data-y="0" class="2345HAO6d36b1ffd157419b cell" py-click="GAME.click"></div></td>
<td><div id="cell11" data-x="1" data-y="1" class="2345HAOb1ffd157419bafa2 cell" py-click="GAME.click"></div></td>
<td><div id="cell12" data-x="1" data-y="2" class="2345HAOd157419bafa2fefc cell" py-click="GAME.click"></div></td>
</tr>
<tr>
<td><div id="cell20" data-x="2" data-y="0" class="2345HAO419bafa2fefc85a7 cell" py-click="GAME.click"></div></td>
<td><div id="cell21" data-x="2" data-y="1" class="2345HAOafa2fefc85a7d532 cell" py-click="GAME.click"></div></td>
<td><div id="cell22" data-x="2" data-y="2" class="2345HAOb6a126f651c30665 cell" py-click="GAME.click"></div></td>
</tr>
</table>
<h2 id="status"></h2>
<button id="btn-new-game" py-click="GAME.new_game">New game</button>
<button id="btn-toggle-terminal" py-click="GAME.toggle_terminal">Hide/show terminal</button>
<div id="terminal" hidden="hidden">
<script id="console" type="py" terminal></script>
</div>
</section>
</body>
</html>
使用应用所需的必要配置(包括依赖项、文件路径等)更新 pyscript.toml 文件。这可确保 PyScript 知道如何正确加载和运行 Python 代码。以下是我们的井字游戏应用的 pyscript.toml 文件内容:
配置:
name = "Tic Tac Toe" description = "A Tic-Tac-Toe game written in PyScript that allows people to take turns."
输出:
这是您在 PScript 上的之一个项目。
Python 在数据科学、人工智能、自动化和教育领域的应用前所未有。然而,迄今为止,Python 在 Web 上尚无原生平台。PyScript 应运而生,它将 Python 的简洁性与 Web 的易用性完美融合。它仍在不断完善,但已经为开发者、教育工作者和学习者创造了大量机会。
本章节主要是对宝塔面板的主界面的各个版本进行一个简单的说明。 宝塔面板主界面主要包括:服务器操作系统、服务器状态、站点信息、软件管理及网络流量几个部分。 Windows面板有部分功能未实现,其余部分与Linux面板同步。 系统操作...
宝塔面板中的网站管理是非常重要的一部分,也是站长经常需要使用到的功能模块。网站管理,主要用于管理和创建WEB站点。如果您是宝塔面板的使用用户,应该对此模块有充分的了解,以便于您更高效地管理网站。 宝塔面板网站管理模块包括:添加新网站、修改默认页、设置默认站点、站点列表、站点的运行与停止、备份站点、...
使用宝塔面板,您可以快速地创建一个FTP管理账户,对网站文件进行管理。但有必要提醒大家的是,使用FTP远不如使用SFTP安全,你可以查看文章“”进一步了解两者之间的差异。 此外,宝塔面板的文件管理模块其实已经能够满足站长的大部分文件管理需求。当然,如果你非得要使用FTP管理服务器文件,可以参照以下...
每台连接到Internet的计算机都有一个Internet协议 (IP) 地址。但是,并非所有IP地址的外观或行为都相同。 如果您使用计算机网络或服务器,了解动态IP和静态IP之间的区别至关重要。通过详细了解每个协议,您可以选择最适合您需求的解决方案。 在本文中,我们将讨论静态和动态IP之间...
宝塔面板的计划任务,主要用于安排和管理需要定时执行的任务,如备份、内存清理等。其实对于大部分站长来说,主要使用该板块的备份网站、备份数据库及释放内存的三个定时任务计划。 Shell脚本的添加 输入任务名称,选择执行周期,输入执行的脚本内容。 注意事项: 输入脚本内容...
对于初学者和那些刚刚进入WordPress开发的人来说,PHP是您可以开始的最佳起点之一。这是一种超级简单直接的语言,使其成为之一,因此相当容易上手,它构成了在线开发的支柱。另外,如果你想在WordPress后端工作,你肯定需要学习它。 但是,如果您不想在昂贵的大学课程上花费数月或数年时间怎么...