新聞中心
長期以來,Python 社區(qū)一直在討論如何使 Python 成為網(wǎng)頁瀏覽器中流行的編程語言。然而網(wǎng)絡(luò)瀏覽器實際上只支持一種編程語言:JavaScript。隨著網(wǎng)絡(luò)技術(shù)的發(fā)展,我們已經(jīng)把越來越多的程序應(yīng)用在網(wǎng)絡(luò)上,如游戲、數(shù)據(jù)科學(xué)可視化以及音頻和視頻編輯軟件。這意味著我們已經(jīng)把繁重的計算帶到了網(wǎng)絡(luò)上——這并不是JavaScript的設(shè)計初衷。所有這些挑戰(zhàn)提出了對新編程語言的需求,這種語言可以提供快速、可移植、緊湊和安全的代碼執(zhí)行。因此,主要的瀏覽器供應(yīng)商致力于實現(xiàn)這個想法,并在2017年向世界推出了WebAssembly。

成都創(chuàng)新互聯(lián)主要從事成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)鄠邑,10年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18980820575
在本教程中,我們將看一下WebAssembly如何幫助你在瀏覽器中運行Python代碼。
要明確的是,JavaScript本身就是一種強大的編程語言。它只是不適合某些操作。關(guān)于這一點,請看JavaScript的創(chuàng)始人Brendan Eich的《從ASM.JS到WebAssembly》一文。
我們正在建立什么
假設(shè)你想教一門Python課程。為了使你的課程更加有趣和好玩,在每一節(jié)課之后,你想為你的學(xué)生安排一個練習(xí),這樣他們就可以練習(xí)他們所學(xué)到的知識。
這里的問題是,學(xué)生需要通過安裝特定版本的Python來準(zhǔn)備一個開發(fā)環(huán)境,創(chuàng)建并激活一個虛擬環(huán)境,并安裝所有必要的包。這可能會耗費大量的時間和精力。由于每臺機器都是不同的,所以也很難對此提供確切的指導(dǎo)。
雖然你可以創(chuàng)建一個后端,在Docker容器或AWS Lambda函數(shù)中運行提交的代碼,但你選擇保持簡單堆棧,在課程內(nèi)容中添加一個Python編輯器,可以在客戶端、在網(wǎng)絡(luò)瀏覽器中運行Python代碼,并向用戶展示結(jié)果。這正是你在本教程中要構(gòu)建的東西。
WebAssembly
根據(jù)Mozilla開發(fā)者網(wǎng)絡(luò)(MDN)文檔的定義,WebAssembly(WASM)的定義如下:
WebAssembly是一種運行在現(xiàn)代網(wǎng)絡(luò)瀏覽器中的新型代碼,并且提供新的性能特性和效果。它設(shè)計的目的不是為了手寫代碼而是為諸如C、C++和Rust等低級源語言提供一個高效的編譯目標(biāo)。
因此,WASM讓我們在瀏覽器中運行用不同語言(不僅僅是JavaScript)編寫的代碼,有以下好處:
- 它是快速、高效和可移植的。
- 它是安全的,因為代碼是在一個安全的沙盒執(zhí)行環(huán)境中運行的。
- 它可以在客戶端運行。
因此,在我們上面的例子中,如果用戶在我們的服務(wù)器上運行代碼,我們不需要擔(dān)心,如果成千上萬的學(xué)生嘗試練習(xí)代碼,我們也不需要擔(dān)心,因為代碼的執(zhí)行發(fā)生在客戶端,在Web瀏覽器上。
WebAssembly的設(shè)計并不是為了殺死JavaScript。它是對JavaScript的補充。當(dāng)JavaScript不是合適的工具時,它可以被使用,如游戲、圖像識別和圖像/視頻編輯等。
請看 WebAssembly.org的使用案例,了解更多你可能想利用WebAssembly的情況。
Pyodide
本教程使用Pyodide庫來運行Python代碼,它將CPython解釋器編譯為WebAssembly,并在瀏覽器的JavaScript環(huán)境中運行。它帶有一些預(yù)裝的Python軟件包。你也可以使用Micropip來使用更多的軟件包。
Hello World
用下面的代碼創(chuàng)建一個新的HTML文件。
在你的瀏覽器中打開該文件。然后,在你的瀏覽器的開發(fā)者工具控制臺中,你應(yīng)該做如下事情:
Loading distutils
Loading distutils from https://cdn.jsdelivr.net/pyodide/v0.20.0/full/distutils.js
Loaded distutils
Python initialization complete
Hello, world from the browser!
你可以看到,最后一行是Python代碼在瀏覽器中執(zhí)行的結(jié)果。
讓我們快速看一下上面的代碼。
- 首先,你可以使用CDN或直接從GitHub發(fā)布的版本下載并安裝Pyodide。
- loadPyodide 加載并初始化 Pyodide wasm 模塊。
- pyodide.runPython將Python代碼作為一個字符串,并返回代碼的結(jié)果。
Pyodide的優(yōu)勢
在前面的例子中,你看到了安裝Pyodide并開始使用它是多么容易。你只需要從CDN導(dǎo)入 pyodide.js并通過 loadPyodide初始化它。之后,你可以使用 pyodide.runPython("你的Python代碼")在瀏覽器中運行你的 Python 代碼。
當(dāng)你第一次下載Pyodide時,下載量很大,因為你要下載完整的CPython解釋器,但你的瀏覽器會緩存它,你不需要再次下載它。
在Pyodide上還有一個龐大而活躍的社區(qū)。其官方網(wǎng)址如下:
??https://pyodide.org/en/stable/ ??
可以看一下其中的Pyodide 路線圖、GitHub上的公開問題、Gitter社區(qū)。
Pyodide的局限性
第一次加載Pyodide,需要四到五秒(取決于你的連接速度),因為你必須下載約10MB左右的文件。另外,Pyodide代碼的運行速度比本地Python慢3到5倍。
其他選擇
一般來說,如果你想在瀏覽器中運行Python,你有兩種方法可用。
1、使用轉(zhuǎn)譯器將Python轉(zhuǎn)換為JavaScript。Brython、Transcrypt 和 Skulpt 都使用這種方法。
2、轉(zhuǎn)換Python運行環(huán)境以在瀏覽器中使用。Pyodide 和 PyPy.js 使用這種方法。
方案一和方案二的一個主要區(qū)別是,方案一中提到的庫不支持Python包。也就是說,它們的下載量比方案二中的庫要小得多,因此,它們的速度也更快。
在這個教程中,我們選擇了Pyodide,因為它的語法更簡單,而且支持Python包。如果你對其他選項感興趣,請隨時查看它們的文檔。
Python代碼編輯器
在本節(jié)中,我們將創(chuàng)建一個簡單的Python編輯器,可以在瀏覽器中運行代碼。
1、Pyodide
2、CodeMirror
3、Flask
創(chuàng)建一個新的項目。
$ mkdir python_editor_wasm
$ cd python_editor_wasm
創(chuàng)建并激活一個虛擬環(huán)境。
$ python3.10 -m venv env
$ source env/bin/activate
(env)$
安裝Flask:
(env)$ pip install Flask
在項目的根部創(chuàng)建一個名為app.py的文件并添加以下代碼。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
在我們項目的根部創(chuàng)建一個 "templates "文件夾,并在其下添加index.html文件。
templates/index.html:
Run Python in your browser
在 index.html文件的頭部,我們導(dǎo)入了用于格式化的Tailwind CSS,Pyodide.js 0.20.0,以及CodeMirror及其依賴包。
UI有三個重要的組成部分:
1、Editor。用戶可以在這里寫Python代碼。它是一個文本區(qū)域的HTML元素,其ID為代碼。當(dāng)我們初始化codemirror時,我們讓它知道我們想用這個元素作為一個代碼編輯器。
2、Output。顯示代碼輸出的地方。它是一個id為output的textarea元素。當(dāng)Pyodide執(zhí)行Python代碼時,它將把結(jié)果輸出到這個元素。我們也在這個元素中顯示一個錯誤信息。
3、Run button。當(dāng)用戶點擊這個按鈕時,我們抓取編輯器元素的值并將其作為一個字符串傳遞給 pyodide.runPython。當(dāng) pyodide.runPython返回結(jié)果時,我們在輸出元素中顯示它。
現(xiàn)在在項目的根部,創(chuàng)建 static/js文件夾。然后,在 js文件夾下,創(chuàng)建一個名為 main.js的新文件。
static/js/main.js:
我們完成了以下步驟:
// find the output element
const output = document.getElementById("output");
// initialize codemirror and pass configuration to support Python and the dracula theme
const editor = CodeMirror.fromTextArea(
document.getElementById("code"), {
mode: {
name: "python",
version: 3,
singleLineStringErrors: false,
},
theme: "dracula",
lineNumbers: true,
indentUnit: 4,
matchBrackets: true,
}
);
// set the initial value of the editor
editor.setValue("print('Hello world')");
output.value = "Initializing...\n";
// add pyodide returned value to the output
function addToOutput(stdout) {
output.value += ">>> " + "\n" + stdout + "\n";
}
// clean the output section
function clearHistory() {
output.value = "";
}
// init pyodide and show sys.version when it's loaded successfully
async function main() {
let pyodide = await loadPyodide({
indexURL: "https://cdn.jsdelivr.net/pyodide/v0.20.0/full/",
});
output.value = pyodide.runPython(`
import sys
sys.version
`);
output.value += "\n" + "Python Ready !" + "\n";
return pyodide;
}
// run the main function
let pyodideReadyPromise = main();
// pass the editor value to the pyodide.runPython function and show the result in the output section
async function evaluatePython() {
let pyodide = await pyodideReadyPromise;
try {
pyodide.runPython(`
import io
sys.stdout = io.StringIO()
`);
let result = pyodide.runPython(editor.getValue());
let stdout = pyodide.runPython("sys.stdout.getvalue()");
addToOutput(stdout);
} catch (err) {
addToOutput(err);
}
}
1、初始化CodeMirror,支持Python和Dracula主題。
2、初始化Pyodide。
3、添加了一個名為 evaluatePython的函數(shù),當(dāng)用戶點擊運行按鈕時執(zhí)行。它將代碼元素的值傳遞給 pyodide.runPython,并通過 addToOutput 在輸出元素中顯示結(jié)果。
4、增加了一個叫 clearHistory的函數(shù),當(dāng)用戶點擊 ClearHistory按鈕時,它將清除輸出元素。
要在本地運行Flask開發(fā)服務(wù)器,請運行:
(env)$ flask run
現(xiàn)在服務(wù)器應(yīng)該在5000端口運行。在你的瀏覽器中導(dǎo)航到 http://127.0.0.1:5000,測試一下代碼編輯器。
總結(jié)
在本教程中,主要講解了如何使用WebAssembly在瀏覽器中運行Python代碼,但一般來說,WebAssembly涵蓋了更廣泛的使用情況。
我們的部署平臺比以往任何時候都更加多樣化。WebAssembly可以影響客戶端Web開發(fā)、服務(wù)器端開發(fā)、游戲、教育、云計算、移動平臺、loT、serverless等方面。
分享標(biāo)題:用WebAssembly在瀏覽器中運行Python
本文路徑:http://fisionsoft.com.cn/article/coihesc.html


咨詢
建站咨詢
