Python Tech

PyScript(alpha版)代码演示

PyConUS2022公布的PyScript可以在浏览器执行Python代码,依赖于pyodide(WebAssembly的CPython)。相比pyodide更接近Web的开发体验。公布的 alpha 版本输出 Python 版本信息是: 3.10.2 (main, Apr 9 2022, 20:52:01) [Clang 14.0.0 (https://github.com/llvm/llvm-project 78e87970af888bbbd5652c31f3a8

下载项目源码,执行 npm run dev 运行的官方 demo 主要针对数据处理和 REPL,本文整理 Web 开发常见的几个代码片段:获取数据,读取本地数据库,事件绑定。

Install

只需要增加HTML标签引入文件:



但会从 cdn.jsdelivr.net 请求 pyodide.asm 相关文件。去年年底开始国内的jsdelivr访问时断时续,整个依赖有22MB,需要先设置好网络。

Usage

在HTML中使用<py-script>标签嵌入Python代码。和<script>标签一样,支持 src 属性直接引入 .py 文件。以Web开发很常用的两个场景,网络请求和访问数据库为例:

网络请求

这一版的pyscript还不能直接用Python库发起Web请求,如果调用 http.client 会报错:

  File "/lib/python3.10/http/client.py", line 941, in connect
    self.sock = self._create_connection(
  File "/lib/python3.10/socket.py", line 845, in create_connection
    raise err
  File "/lib/python3.10/socket.py", line 833, in create_connection
    sock.connect(sa)
BlockingIOError: [Errno 26] Operation in progress

即使用 asyncio 处理,也默认是浏览器发起 WebSocket 连接。

可以调用 pyodide.http.open_url 或使用 Javascript 的 fetch 从接口获取数据并在页面显示的代码:

 
Key Value
import asyncio from pyodide.http import open_url import json from js import fetch, document #调用Javascript的 fetch方法和document async def request_github_api(): url = "https://api.github.com/" r = await fetch(url) data = await r.json() # data = json.loads(open_url(url).read()) # open_url 读取数据,json处理成 dict rows = document.getElementById("table-data-rows") # 循环体的处理都是 Javascript 语法 for k, v in data.object_entries(): # for k, v in data.items(): # open_url 返回的 dict tr = document.createElement('tr') key_td, value_td = document.createElement('td'), document.createElement('td') key_td.innerHTML = k value_td.innerHTML = v tr.append(key_td, value_td) rows.appendChild(tr) asyncio.ensure_future(request_github_api())

访问数据库

pyodide支持的 Python 包列表: https://github.com/pyodide/pyodide/tree/main/packages

已经支持 Sqlalchemy 这个主要的 ORM 包。因为缺少依赖且浏览器有限制,还不能连接远程数据库,但可以使用 Sqlite 的 inmemory 模式,代码如下:

    
      - sqlalchemy # 其他包使用  引入
    
    
from sqlalchemy import create_engine, text

engine = create_engine("sqlite+pysqlite:///:memory:", future=True) # Sqlite 连接
with engine.connect() as conn:
    conn.execute(text("CREATE TABLE sites (name string, domain string)")) # 建表,写数据,提交
    conn.execute(
            text("INSERT INTO sites (name, domain) VALUES (:name, :domain)"),
            [{"name": "Dmyz1", "domain": "http://dmyz.org"}, {"name": "Dmyz2", "domain": "http://dmyz.net"}],
        )
    conn.commit()

    result = conn.execute(text("SELECT * FROM sites"))
    for row in result.all(): # 遍历结果。之前已经写过 DOM 的处理,这里直接 print
        print("Site: {}, Domain: {}".format(row[0], row[1]))

    

事件绑定

PyScript 使用 pys-{EVENT} 属性在 HTML 标签上绑定事件,例如点击按钮获取时间戳:


import time def get_time(*args, **kwargs): Element("current-time").write(time.time())

Afterwords

WebAssembly也发展近十年了,“让浏览器运行C/C++代码”听起来如同 nodejs 一样的新颖,然而只有一些简单的游戏演示,在 Web 应用方面让人眼前一亮的项目并不多。前几年接触iodide和pyodide的时候,也只觉得和 Jupyterhub 比较像,没想到合适的用途。

这次再看到 PyScript ,似乎只是 pyodide 加了几个 HTML 标签,但用起来顺手很多。第一印象是 PHP/JSP 曾经的混合写法,实际上手就发现它已经推进了 WebAssembly 的目标:让 C(Python)/C++ 成为真正能直接被浏览器解析,简单易上手的语言。虽然受限于网速、浏览器性能等因素,还替代不了 Javascript,但对于一些特定领域尤其是 Python 擅长的数据处理/机器学习,PyScript 应该能从 Javascript 分走一些。而且 Python 工程师们,以后就是名副其实的 Web 全栈了。

订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论