Brython Web 中实现 Python 3 的运行
Brython 中文网
Brython(Browser Python)是 Web 的脚本语言,具有 DOM 元素和事件的接口, 可以在 HTML5 环境下编写、导入和执行 python3 脚本,创建和操作 DOM 等。
源码 mirrors-brython-master 认真阅读 README.md
一、安装 Brython
假设 PC 上装有 python 及 pip,安装 brython 模块:
pip install brython
pip install brython --upgrade (更新)
新建目录 python_line_editor,然后在此录下运行:
python -m brython --install
python -m brython --update (更新)
usage: -m mod : run library module as a script (terminates option list)
brython.js:包含在 HTML 页面中的 Brython 引擎,包括经常使用的模块:browser, browser.html, javascript。
brython_stdlib.js:对 Brython 支持的 Python 标准库部分的所有模块和包进行分组。
demo.html:一个页面,其中包含一些如何使用 Brython 进行客户端开发的示例。
python -m brython --modules
创建特定于应用程序的分发,以替换 brython_stdlib.js为较小的文件。
python -m brython --make_dist
生成一个 CPython 包,适合 PyPI 发布,安装一个 Brython 应用程序。
安装 Brython 分:Zero install ! 和 Local install
以下是浏览器和 Javascript 强加的一些功能和限制:
- 在转到下一条指令之前,Javascript 函数不能阻止给定时间的执行或等待事件发生。为此原因:
- time.sleep() 不能使用:模块 browser.timer 中的函数,例如 set_timeout() 或 set_interval() 必须使用
- 内置函数 input() 由 Javascript 函数模拟 prompt()
- 出于同样的原因,并且因为浏览器有自己的隐式事件循环,CPython asyncio 模块不可用。特定 browser.aio 于 Brython 的模块用于异步编程。
- 内置函数 open() 将要打开的文件的 url 作为参数。由于它是使用 Ajax 调用读取的,因此它必须与脚本位于同一个域中。返回的对象 open() 具有通常的读取和访问方法:read, readlines, seek, tell, close。仅支持文本模式:Ajax 调用正在阻塞,在此模式下 responseType 无法设置属性
- 默认情况下,print() 将输出到 Web 浏览器控制台,错误消息也是如此。sys.stderr 和 sys.stdout 可以将其分配给对象(定义了 write() 方法),这允许将输出重定向到例如窗口或文本区域。
- 打开打印对话框(打印机),调用 window.print(window 在模块浏览器中定义)。
- sys.stdin 此时未实现,但是有一个 input() 内置函数将打开阻塞输入对话框(提示)。
- 对象生命周期由 Javascript 垃圾收集器管理,Brython 不像 CPython 那样管理引用计数。因此,del()当不再引用类实例时,不会调用方法。
- JSON 解析器使用 Javascript; 因此,等于整数的实数(例如1.0)将被转换为整数 json.dumps()。
二、应用
To use Brython, all there is to do is:
- Load the script brython.js.
- Run the function brython() on page load, like .
- Write Python code inside tags
如果你的应用程序使用标准分布的模块,你除了 brython.js 之外还需要包括 brython_stdlib.js:
<!-- index.html -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<!-- 分三步 第一步 加载 brython.js -->
<script type="text/javascript" src="brython.js"></script>
<script type="text/javascript" src="brython_stdlib.js"></script>
</head>
<!-- 第二步 添加属性 -->
<body onload="brython()">
<!-- 第三步 编写 python 脚本 -->
<script type="text/python3">
from browser import document, html
document <= "Hello !"
document <= html.B("Hello !")
document <= html.B(html.I("Hello !")) # 标签可以嵌套
document <= html.B("Hello, ") + "world !" # 标签和字符串也可以相互添加
document <= html.B(html.I("Hello !") + " World")
# document <= html.UL(html.LI(i) for i in range(5))
document <= html.UL(html.LI(i) for i in ['Python','java','C'])
document <= html.A("Brython", href="http://brython.info")
</script>
<script type="text/python3" src="test.py"></script>
<input id="zone"><button id="btn">click !</button>
</body>
</html>
test.py 文件
from browser import document as doc, alert
def echo(e):
print('This is a function')
alert(doc["zone"].value)
# 给按钮绑定事件‘click’到方法‘echo’上
doc["btn"].bind("click",echo)
在 brython 目录中,将此页面另存为 index.html。
启动一个 Web 服务器:在文件目录中运行 python -m http.server 8080,然后在浏览器地址栏中输入 localhost:8080/index.html
1、页面结构
在 head 区域中,加载脚本 brython.js (Brython 引擎),该程序将查找并执行页面中包含的 Python 脚本。
body 标记具有 onload =“brython()” 属性。这意味着页面完成加载后,浏览器必须调用函数 brython(),该函数在页面加载的 Brython 引擎中定义。该函数搜索所有具有 type =“text/python3” 属性的 script 标记并执行它们。
页面嵌入了以下脚本:
<script type=“text/python3” src=“test.py”>
from browser import document
</script>
这是一个标准的 Python 程序,首先导入模块浏览器(为 Brython 引擎 brython.js 随附的模块)。该模块具有一个属性 document (浏览器窗口中显示的内容)。
要将文本添加到 document 中,也就是在浏览器中显示文本-Brython 使用的语法是
document <= "Hello !"
可以将 <= 符号视为左箭头:document “接收”一个新元素,此处为字符串 “ Hello!”。总是可以使用标准化的 DOM 语法与页面进行交互。
如果 Python 程序很大,另一个选择是将它写在一个单独的文件中,并使用脚本标记的 src 属性加载它:
<script type=“text/python” src=“test.py”> </script>
<!-- http://localhost:8080/index.html 下运行通过 -->
请注意,在这种情况下,Python 脚本将通过 Ajax 调用加载:它必须与 HTML 页面位于同一个域中。
在上面代码示例中,当我们单击按钮时,onclick 事件会调用并运行 echo() 在 Python 脚本中定义的函数。此函数通过其 id 获取 INPUT 元素的值。这是通过以下语法实现的 document[“zone”]:document 在模块浏览器中定义,是表示当前在浏览器中显示的文档的对象。它的行为类似于字典,其键是 DOM 元素的 ID。因此,在我们的示例中, document[“zone”] 是一个映射到 INPUT 元素的对象。
在 Brython 中,输出可以通过各种方式完成,包括使用函数 alert()(也在浏览器中定义),该函数显示弹出窗口,文本作为参数传递。
2、内容标签化
HTML 标签允许文本格式设置,例如以粗体字母(B 标签),斜体(I 标签)等形式书写。
对于 Brython,这些标签可利用 browser 包的 html 模块中定义的功能来实现。使用方法如下:
from browser import document, html
document <= html.B("Hello !")
document <= html.B(html.I("Hello !")) # 标签可以嵌套
document <= html.B("Hello, ") + "world !" # 标签和字符串也可以相互添加
标签函数的第一个参数可以是字符串,数字,另一个标签。它也可以是 Python 中“可迭代的”(list,comprehension,generator):在这种情况下,将迭代中生成的所有元素都添加到标签内:
document <= html.UL(html.LI(i) for i in range(5))
标签属性作为关键字参数传递给函数:
document <= html.A("Brython", href="http://brython.info")
3、绘制计算器
可以用 HTML 表格绘制一个计算器。
第一行由结果区域组成,后跟一个重置按钮。接下来的3行是计算器的数字和运算符。
from browser import document, html
calc = html.TABLE()
calc <= html.TR(html.TH(html.DIV("0", id="result"), colspan=3) +
html.TH("C", id="clear"))
lines = ["789/",
"456*",
"123-",
"0.=+"]
calc <= (html.TR(html.TD(x) for x in line) for line in lines)
document <= calc
请注意使用 Python 生成器来减小程序大小,同时保持可读性。
让我们来添加样式,以使计算器看起来更好:
<style>
*{
font-family: sans-serif;
font-weight: normal;
font-size: 1.1em;
}
td{
background-color: #ccc;
padding: 10px 30px 10px 30px;
border-radius: 0.2em;
text-align: center;
cursor: default;
}
#result{
border-color: #000;
border-width: 1px;
border-style: solid;
padding: 10px 30px 10px 30px;
text-align: right;
}
</style>
4、事件处理
下一步是在用户按下计算器按键时触发动作:
1)数字和运算:在结果区域中打印数字或运算
2)=符号:执行操作并打印结果,如果输入无效,则显示错误消息
3)C符号:重置结果区域
要处理打印在页面中的元素,程序首先需要获得对它们的引用。这些按钮已被创建为标签。为了获得所有这些标签的引用,语法是
document.select("td")
传递给 select() 方法的参数是 CSS 选择器。最常用的是:标记名(“td”),元素的 id 属性 ("#result") 或其属性 “class”(".classname")。select() 的结果始终是元素列表。
页面元素上可能发生的事件具有标准化名称:当用户单击按钮时,将触发名为 “cick” 的事件。在程序中,此事件会激发功能的执行。元素,事件和功能之间的关联由语法定义
element.bind("click", action)
对于计算器,我们可以通过以下方式将相同功能与所有按钮上的“ click”事件相关联:
for button in document.select("td"):
button.bind("click", action)
为了符合 Python 语法,必须在程序中的某个位置定义 action 函数。这样的“回调”函数采用单个参数,即表示事件的对象。
5、完成编码
这是实现一个简易计算器的代码。最重要的部分是函数 action(event)。
from browser import document, html
# Construction de la calculatrice
calc = html.TABLE()
calc <= html.TR(html.TH(html.DIV("0", id="result"), colspan=3) +
html.TD("C"))
lines = ["789/", "456*", "123-", "0.=+"]
calc <= (html.TR(html.TD(x) for x in line) for line in lines)
document <= calc
result = document["result"] # direct acces to an element by its id
def action(event):
"""Handles the "click" event on a button of the calculator."""
# The element the user clicked on is the attribute "target" of the
# event object
element = event.target
# The text printed on the button is the element's "text" attribute
value = element.text
if value not in "=C":
# update the result zone
if result.text in ["0", "error"]:
result.text = value
else:
result.text = result.text + value
elif value == "C":
# reset
result.text = "0"
elif value == "=":
# execute the formula in result zone
try:
result.text = eval(result.text)
except:
result.text = "error"
# Associate function action() to the event "click" on all buttons
for button in document.select("td"):
button.bind("click", action)
三、小结 Brython 运行环境
1、brython.js
<script type="text/javascript" src="brython.js"></script>
<script type="text/javascript" src="brython_stdlib.js"></script>
<!--
<script type="text/javascript"
src="https://cdn.jsdelivr.net/npm/brython@3.8.9/brython.min.js"> </script>
-->
brython.js 是 Brython 核心组件库(Brython Core Components)。主要有这几个核心组件:
brython() 函数
这是暴露给 JavaScript 命名空间的一个最主要的函数,也是唯一一个需要显示调用的一个 JavaScript 函数。
browser
这是通常意义上用 JavaScript 交互的 document 和 window 对象的 Python 实现模块。
除了 brython.js,还有另外一个库是 brython_stdlib.js,它实现的是 Brython 标准库(Brython Standard Library)。
2、文档加载结束时,要调用 brython() 函数。
<body onload="brython()">
3、将 script 标签的语言类型设置为 Python。
<script type="text/python">
brython() 函数会把当前节点范围内带 type=“text/python3” 的 script 脚本都翻译为 JavaScript 执行。
在浏览器环境下运行,也有不少限制。比如不能直接访问文件系统,不能使用 os 库等与浏览器环境不相关的库等。
Brython,可以使用 Python 语言来操作浏览器 API 和 DOM 。并且还有机会和已有的 JS 代码框架进行交互,合理利用已有的 JS 功能。
<script type="text/javascript">
function messageBox(name) {
window.alert(`Hello ${name}!`);
}
</script>
<script type="text/python">
from browser import window
window.messageBox("Yake")
print("Hello World!")
</script>
4、DOM api
使用 Brython,DOM API 中描述的所有操作都依赖于模块浏览器中定义的两个对象:document 和 window
document 实现 DOM API 中定义的接口。例如,它支持以下方法:
document.getElementById(elt_id) # 返回对 id 为 elt_id 的 DOM 元素的引用
document.createElement(tagName) # 返回 tagName 类型的新元素;
# 例如,要创建超文本链接:
link = document.createElement('A')
document.appendChild(elt) # 将元素elt添加到文档中
除了这个标准接口,Brython 还提出了一个替代接口,对于 Brython 开发人员来说更为熟悉。
Brython 用于编写 Web 应用程序,因此用户可以与之交互的 HTML 页面。
页面由元素(文本,图像,声音…)组成,可以通过两种不同的方式包含在页面中:
例如,用标签编写HTML代码
<html>
<body>
<b>Brython</b> is an implementation of <a href="http://www.python.org">Python</a>
for web browsers
</body>
</html>
或使用内置模块 browser.html 动态的编写 Python 代码
<html>
<body>
<script type="text/python3">
from browser import document
from browser.html import A,B
document <= B("Brython")+"is an implementation of "
document <= A("Python",href="http://www.python.org")+" for web browsers"
</script>
</body>
</html>