<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用 WebAssembly 在瀏覽器中運(yùn)行 Python

          共 5686字,需瀏覽 12分鐘

           ·

          2022-04-28 00:37

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

          在本教程中,我們將看一下WebAssembly如何幫助你在瀏覽器中運(yùn)行Python代碼。

          要明確的是,JavaScript本身就是一種強(qiáng)大的編程語言。它只是不適合某些操作。關(guān)于這一點(diǎ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)境,并安裝所有必要的包。這可能會耗費(fèi)大量的時間和精力。由于每臺機(jī)器都是不同的,所以也很難對此提供確切的指導(dǎo)。

          雖然你可以創(chuàng)建一個后端,在Docker容器或AWS Lambda函數(shù)中運(yùn)行提交的代碼,但你選擇保持簡單堆棧,在課程內(nèi)容中添加一個Python編輯器,可以在客戶端、在網(wǎng)絡(luò)瀏覽器中運(yùn)行Python代碼,并向用戶展示結(jié)果。這正是你在本教程中要構(gòu)建的東西。

          WebAssembly

          根據(jù)Mozilla開發(fā)者網(wǎng)絡(luò)(MDN)文檔的定義,WebAssembly(WASM)的定義如下:

          WebAssembly是一種運(yùn)行在現(xiàn)代網(wǎng)絡(luò)瀏覽器中的新型代碼,并且提供新的性能特性和效果。它設(shè)計(jì)的目的不是為了手寫代碼而是為諸如C、C++和Rust等低級源語言提供一個高效的編譯目標(biāo)。

          因此,WASM讓我們在瀏覽器中運(yùn)行用不同語言(不僅僅是JavaScript)編寫的代碼,有以下好處:

          • 它是快速、高效和可移植的。

          • 它是安全的,因?yàn)榇a是在一個安全的沙盒執(zhí)行環(huán)境中運(yùn)行的。

          • 它可以在客戶端運(yùn)行。

          因此,在我們上面的例子中,如果用戶在我們的服務(wù)器上運(yùn)行代碼,我們不需要擔(dān)心,如果成千上萬的學(xué)生嘗試練習(xí)代碼,我們也不需要擔(dān)心,因?yàn)榇a的執(zhí)行發(fā)生在客戶端,在Web瀏覽器上。

          WebAssembly的設(shè)計(jì)并不是為了殺死JavaScript。它是對JavaScript的補(bǔ)充。當(dāng)JavaScript不是合適的工具時,它可以被使用,如游戲、圖像識別和圖像/視頻編輯等。

          請看 WebAssembly.org的使用案例,了解更多你可能想利用WebAssembly的情況。

          Pyodide

          本教程使用Pyodide庫來運(yùn)行Python代碼,它將CPython解釋器編譯為WebAssembly,并在瀏覽器的JavaScript環(huán)境中運(yùn)行。它帶有一些預(yù)裝的Python軟件包。你也可以使用Micropip來使用更多的軟件包。

          Hello World

          用下面的代碼創(chuàng)建一個新的HTML文件。

          在你的瀏覽器中打開該文件。然后,在你的瀏覽器的開發(fā)者工具控制臺中,你應(yīng)該做如下事情:

          1. Loading distutils

          2. Loading distutils from https://cdn.jsdelivr.net/pyodide/v0.20.0/full/distutils.js

          3. Loaded distutils

          4. Python initialization complete

          5. 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代碼")在瀏覽器中運(yùn)行你的 Python 代碼。

          當(dāng)你第一次下載Pyodide時,下載量很大,因?yàn)槟阋螺d完整的CPython解釋器,但你的瀏覽器會緩存它,你不需要再次下載它。

          在Pyodide上還有一個龐大而活躍的社區(qū)。其官方網(wǎng)址如下:

          https://pyodide.org/en/stable/

          可以看一下其中的Pyodide 路線圖、GitHub上的公開問題、Gitter社區(qū)。

          Pyodide的局限性

          第一次加載Pyodide,需要四到五秒(取決于你的連接速度),因?yàn)槟惚仨毾螺d約10MB左右的文件。另外,Pyodide代碼的運(yùn)行速度比本地Python慢3到5倍。

          其他選擇

          一般來說,如果你想在瀏覽器中運(yùn)行Python,你有兩種方法可用。

          1、使用轉(zhuǎn)譯器將Python轉(zhuǎn)換為JavaScript。Brython、Transcrypt 和 Skulpt 都使用這種方法。

          2、轉(zhuǎn)換Python運(yùn)行環(huán)境以在瀏覽器中使用。Pyodide 和 PyPy.js 使用這種方法。

          方案一和方案二的一個主要區(qū)別是,方案一中提到的庫不支持Python包。也就是說,它們的下載量比方案二中的庫要小得多,因此,它們的速度也更快。

          在這個教程中,我們選擇了Pyodide,因?yàn)樗恼Z法更簡單,而且支持Python包。如果你對其他選項(xiàng)感興趣,請隨時查看它們的文檔。

          Python代碼編輯器

          在本節(jié)中,我們將創(chuàng)建一個簡單的Python編輯器,可以在瀏覽器中運(yùn)行代碼。

          1、Pyodide 2、CodeMirror 3、Flask

          創(chuàng)建一個新的項(xiàng)目。

          1. $ mkdir python_editor_wasm

          2. $ cd python_editor_wasm

          創(chuàng)建并激活一個虛擬環(huán)境。

          1. $ python3.10 -m venv env

          2. $ source env/bin/activate

          3. (env)$

          安裝Flask:

          1. (env)$ pip install Flask

          在項(xiàng)目的根部創(chuàng)建一個名為app.py的文件并添加以下代碼。

          1. from flask import Flask, render_template


          2. app = Flask(__name__)


          3. @app.route('/')

          4. def index():

          5. return render_template('index.html')


          6. if __name__ == '__main__':

          7. app.run(debug=True)

          在我們項(xiàng)目的根部創(chuàng)建一個 "templates "文件夾,并在其下添加index.html文件。

          templates/index.html:

          1. class="h-full bg-slate-900">

          2. charset="UTF-8">

          3. name="viewport" content="width=device-width, initial-scale=1.0">

          4. rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/codemirror.min.css" />

          5. rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.63.3/theme/dracula.css"/>

          6. class="h-full overflow-hidden max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mt-8">

          7. class="text-slate-200 text-3xl my-4 font-extrabold mx-2 pt-8">Run Python in your browser

          8. class="h-3/4 flex flex-row">

          9. class="grid w-2/3 border-dashed border-2 border-slate-500 mx-2">

          10. id="code" name="code" class="h-full">

        2. class="grid w-1/3 border-dashed border-2 border-slate-500 mx-2">

        3. readonly class="p-8 text-slate-200 bg-slate-900" id="output" name="output">

        4. onclick="evaluatePython()" type="button" class="mx-2 my-4 h-12 px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm bg-green-700 hover:bg-green-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-700 text-slate-300">Run

        5. onclick="clearHistory()" type="button" class="mx-2 my-4 h-12 px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm bg-red-700 hover:bg-red-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-700 text-slate-300">Clear History

        6. 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)用戶點(diǎn)擊這個按鈕時,我們抓取編輯器元素的值并將其作為一個字符串傳遞給 pyodide.runPython。當(dāng) pyodide.runPython返回結(jié)果時,我們在輸出元素中顯示它。

          現(xiàn)在在項(xiàng)目的根部,創(chuàng)建 static/js文件夾。然后,在 js文件夾下,創(chuàng)建一個名為 main.js的新文件。

          static/js/main.js

          1. // find the output element

          2. const output = document.getElementById("output");


          3. // initialize codemirror and pass configuration to support Python and the dracula theme

          4. const editor = CodeMirror.fromTextArea(

          5. document.getElementById("code"), {

          6. mode: {

          7. name: "python",

          8. version: 3,

          9. singleLineStringErrors: false,

          10. },

          11. theme: "dracula",

          12. lineNumbers: true,

          13. indentUnit: 4,

          14. matchBrackets: true,

          15. }

          16. );

          17. // set the initial value of the editor

          18. editor.setValue("print('Hello world')");

          19. output.value = "Initializing...\n";


          20. // add pyodide returned value to the output

          21. function addToOutput(stdout) {

          22. output.value += ">>> " + "\n" + stdout + "\n";

          23. }


          24. // clean the output section

          25. function clearHistory() {

          26. output.value = "";

          27. }


          28. // init pyodide and show sys.version when it's loaded successfully

          29. async function main() {

          30. let pyodide = await loadPyodide({

          31. indexURL: "https://cdn.jsdelivr.net/pyodide/v0.20.0/full/",

          32. });

          33. output.value = pyodide.runPython(`

          34. import sys

          35. sys.version

          36. `);

          37. output.value += "\n" + "Python Ready !" + "\n";

          38. return pyodide;

          39. }


          40. // run the main function

          41. let pyodideReadyPromise = main();


          42. // pass the editor value to the pyodide.runPython function and show the result in the output section

          43. async function evaluatePython() {

          44. let pyodide = await pyodideReadyPromise;

          45. try {

          46. pyodide.runPython(`

          47. import io

          48. sys.stdout = io.StringIO()

          49. `);

          50. let result = pyodide.runPython(editor.getValue());

          51. let stdout = pyodide.runPython("sys.stdout.getvalue()");

          52. addToOutput(stdout);

          53. } catch (err) {

          54. addToOutput(err);

          55. }

          56. }

          我們完成了以下步驟:

          1、初始化CodeMirror,支持Python和Dracula主題。

          2、初始化Pyodide。

          3、添加了一個名為 evaluatePython的函數(shù),當(dāng)用戶點(diǎn)擊運(yùn)行按鈕時執(zhí)行。它將代碼元素的值傳遞給 pyodide.runPython,并通過 addToOutput 在輸出元素中顯示結(jié)果。

          4、增加了一個叫 clearHistory的函數(shù),當(dāng)用戶點(diǎn)擊 ClearHistory按鈕時,它將清除輸出元素。

          要在本地運(yùn)行Flask開發(fā)服務(wù)器,請運(yùn)行:

          1. (env)$ flask run

          現(xiàn)在服務(wù)器應(yīng)該在5000端口運(yùn)行。在你的瀏覽器中導(dǎo)航到 http://127.0.0.1:5000,測試一下代碼編輯器。

          總結(jié)

          在本教程中,主要講解了如何使用WebAssembly在瀏覽器中運(yùn)行Python代碼,但一般來說,WebAssembly涵蓋了更廣泛的使用情況。

          我們的部署平臺比以往任何時候都更加多樣化。WebAssembly可以影響客戶端Web開發(fā)、服務(wù)器端開發(fā)、游戲、教育、云計(jì)算、移動平臺、loT、serverless等方面。

          本文完整源代碼請掃描下方二維碼加入會員后獲取

          - 點(diǎn)擊下方閱讀原文加入社區(qū)會員 -


          瀏覽 53
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美精品成人自拍视频在线观看 | 青青操青青摸 | 黄色a级三级毛片免费 | 土豪胖哥酒店微信高价的御范气质身材苗条匀称 | 无码日本精品XXXXXXXXX |