无法扩展该卷 因为群集的数量将超过文件系统_浏览器将支持Python项目!Mozilla发布Pyodide...
近日,Mozilla 發布了一個實驗項目 Pyodide,旨在瀏覽器內運行一個完整的 Python 數據科學堆棧。
鏈接:
https://github.com/iodide-project/pyodide/
Pyodide 的創意起源于 Mozilla 的另一個項目 Iodide,Iodide 是一款基于最先進 Web 技術的數據科學實驗和通信工具。值得注意的是,它是設計用于在瀏覽器中,而不是在遠程內核上執行數據科學計算的。
不幸的是,瀏覽器中“人人都有的語言”JavaScript,不僅沒有成熟的數據科學庫,還缺少許多對數值計算有用的功能,例如運算符重載。一方面我們認為業界應該改變這一現狀,并推動 JavaScript 數據科學生態系統向前發展;另一方面我們找到了一條捷徑:那就是將流行且成熟的 Python 科學棧引入瀏覽器來滿足數據科學家的需求。
此外還有更多人認為,Python 語言面臨的一種生存威脅就是無法在瀏覽器內運行,當下有如此多的用戶交互是在網絡或移動設備上發生的,Python 要么融入其中,要么就會逐漸落伍。因此,盡管 Pyodide 首先是要滿足 Iodide 的需求,但它獨立工作時也是由自己用武之地的:
https://github.com/iodide-project/pyodide/blob/master/docs/using_pyodide_from_javascript.md
from js import document, iodidecanvas = iodide.output.element('canvas')
canvas.setAttribute('width', 450)
canvas.setAttribute('height', 300)
context = canvas.getContext("2d")
context.strokeStyle = "#df4b26"
context.lineJoin = "round"
context.lineWidth = 5
pen = False
lastPoint = (0, 0)
def onmousemove(e):
global lastPoint
if pen:
newPoint = (e.offsetX, e.offsetY)
context.beginPath()
context.moveTo(lastPoint[0], lastPoint[1])
context.lineTo(newPoint[0], newPoint[1])
context.closePath()
context.stroke()
lastPoint = newPoint
def onmousedown(e):
global pen, lastPoint
pen = True
lastPoint = (e.offsetX, e.offsetY)
def onmouseup(e):
global pen
pen = False
canvas.addEventListener('mousemove', onmousemove)
canvas.addEventListener('mousedown', onmousedown)
canvas.addEventListener('mouseup', onmouseup)
它輸出成這樣:
想要了解 Pyodide 還可以做哪些事情,最好的方法就是去試一試!這里有一個示例筆記(https://alpha.iodide.io/notebooks/300/,50MB)介紹了它的高級功能。下文將深入探討其工作原理。
現有技術在 Pyodide 誕生之前,已經有許多令人印象深刻的項目將 Python 引入瀏覽器了。然而,包括 NumPy、Pandas、Scipy 和 Matplotlib 在內的這些項目都沒有做到實現全功能主流數據科學棧的程度。
像 Transcrypt 這樣的項目會將 Python 轉換為 JavaScript。因為轉換步驟是在 Python 中完成的,所以你需要提前做好所有轉換,或者連上一臺服務器來完成這項工作。這也無法滿足我們的需求,也就是讓用戶在瀏覽器中編寫 Python,并在沒有任何外部輔助的情況下運行代碼。
像 Brython 和 Skulpt 這樣的項目是將標準 Python 解釋器重寫為 JavaScript,因此它們可以直接在瀏覽器中運行 Python 代碼串。但由于它們是 Python 的全新實現,并且需要在 JavaScript 中引導,因此它們與用 C 編寫的 Python 擴展,例如 NumPy 和 Pandas 等并不兼容,也就沒有數據科學工具可用。
PyPyJs 是 Python 的實時編譯工具 PyPy 的變體,其使用 emscripten 即時編譯 Python 到瀏覽器上。和 PyPy 一樣,它也有能力快速運行 Python 代碼。但它也和 PyPy 一樣在 C 語言擴展的性能方面存在問題。
上面這些方法都需要我們重寫科學計算工具以獲得足夠的性能。我曾為 Matplotlib 做過很多工作,所以知道重寫代碼得花費多少勞力:這條路其他項目已經嘗試過且舉步維艱,而且它要做的工作肯定不是我們這支拼湊起來的新團隊能夠處理的。因此,我們需要構建一個盡可能基于 Python 的標準實現和多數數據科學家正在使用的科學棧的工具。
與 Mozilla 的幾位 WebAssembly 專家討論之后,我們意識到開發這個工具的關鍵在于 emscripten 和 WebAssembly:它們是用來將 C 語言編寫的現有代碼移植到瀏覽器上的技術。隨后我們發現了一個使用 Python 構建的高水平 empscripten 實現,也就是 cpython-emscripten(https://github.com/dgym/cpython-emscripten),最后它成為了 Pyodide 的基礎。
emscripten 和 WebAssembly可以從很多角度來介紹 emscripten 的內容,但對我們而言最重要的是它的兩項用途:
將 C/C++ 編譯到 WebAssembly
作為兼容層,在瀏覽器中模仿原生計算環境
WebAssembly 是一種在現代 Web 瀏覽器中運行的新語言,是 JavaScript 的補充。它是一種類似于群集的底層語言,旨在作為 C 和 C++ 等底層語言的編譯目標,提供接近原生環境的性能。值得注意的是,最流行的 Python 解釋器 CPython 就是用 C 實現的,所以這里就是 emscripten 的用武之地了。
Pyodide 的工作流程如下:
下載主流 Python 解釋器(CPython,https://github.com/python/cpython)的源代碼,以及科學計算包(NumPy 等);
進行很小的調整以使其適應新環境;
使用 emscripten 的編譯器將它們編譯為 WebAssembly。
如果你直接把這個 WebAssembly 輸出加載到瀏覽器中,那么 Python 解釋器就會和在操作系統中直接運行時有很大區別。例如,Web 瀏覽器沒有文件系統(加載和保存文件的位置)。還好 emscripten 提供了一個用 JavaScript 編寫的虛擬文件系統供 Python 解釋器使用。默認情況下,這些虛擬“文件”會駐留在瀏覽器選項卡臨時占用的內存里,頁面關閉時它們就會消失。(emscripten 還為文件系統提供了一種在瀏覽器的本地存儲空間中存儲內容的方法,但 Pyodide 不用它。)
通過模擬文件系統和其它標準計算環境中的功能,emscripten 可以只用很少的調整就將現有項目遷移到 Web 瀏覽器中。(將來我們可能會轉而使用 WASI 作為系統仿真層,但是現在 emscripten 是更成熟和完善的選擇)。
總而言之,要在瀏覽器中加載 Pyodide,你需要下載:
用 WebAssembly 編譯的 Python 解釋器。
emscripten 提供的一些 JavaScript,用于系統仿真。
一個打包的文件系統,包含 Python 解釋器所需的所有文件,其中最重要的是 Python 標準庫。
這些文件可能會非常大:Python 本身為 21MB,NumPy 為 7MB,依此類推。所幸這些包只需要下載一次,之后它們會存儲在瀏覽器的緩存中。
將所有這些東西組合起來后,Python 解釋器就可以訪問其標準庫中的文件,啟動,然后開始運行用戶代碼了。
哪些部分正常工作,哪些不行我們用 CPython 的單元測試作為 Pyodide 持續測試的一部分,以便了解 Python 的哪些功能正常工作,哪些不行。有些東西,比如多線程現在就不能用了,但在新出現的 WebAssembly threads 的幫助下,我們應該很快就能提供支持了。
由于瀏覽器的安全沙箱限制,一些功能(如底層網絡套接字,https://docs.python.org/3/library/socket.html)不太可能正常工作。另外很抱歉讓你失望了,想要在 Web 瀏覽器中運行 Python minecraft 服務器(https://github.com/Yardanico/puremine)可能還有很長的路要走。不過你仍然可以使用瀏覽器的 API 通過網絡獲取內容(后文會具體介紹)。
它有多快?在 JavaScript 虛擬機中運行 Python 解釋器會損失更多性能,但這種懲罰是很小的——在我們的基準測試中,Firefox 上比原生慢 1 到 12 倍,Chrome 上慢 1 到 16 倍。經驗表明,這個程度的性能對于交互探索已經很夠用了。
要注意的是,在 Python 中運行大量內部循環的代碼往往比使用 NumPy 執行其內部循環的代碼慢很多。以下是在 Firefox 和 Chrome 中運行各種 Pure Python 和 Numpy 基準測試(https://github.com/iodide-project/pyodide/tree/master/benchmark/benchmarks)的結果,與在相同硬件上原生運行做對比。
Python 和 JavaScript 的交互如果 Pyodide 能做的就只是運行 Python 代碼并寫入標準輸出,那么它就只能當一個很酷的玩具,但難以用于實際工作。Pyodide 真正的力量在于它能夠以非常高的水平與瀏覽器 API 和其他 JavaScript 庫交互。WebAssembly 旨在輕松地與瀏覽器中運行的 JavaScript 交互。由于我們已經將 Python 解釋器編譯為 WebAssembly,因此它也與 JavaScript 這邊深度集成在了一起。
Pyodide 會隱式轉換 Python 和 JavaScript 之間的許多內置數據類型。其中一些轉換是明顯、直截了的,但有趣的部分向來都在于那些少見的情況。
Python 將 dict 和 object 實例視為兩種不同的類型。dict(字典)只是鍵的映射值。另一方面,object 通常具有對這些對象“做某事”的方法。在 JavaScript 中,這兩個概念被混合成一個名為 Object 的類型。(是的,我在這里簡化了很多內容。)
如果沒有真正理解開發者使用 JavaScript 的 Object 的意圖,就沒法判斷它是該轉換為 Python 的 dict 還是 object。因此,我們必須使用代理,用“鴨子類型”來解決問題。
代理是另一種語言中變量的包裝器。代理不是簡單地在 JavaScript 中讀取變量并根據 Python 的構造重寫它,就像對基本類型所做的那樣,而是維持原始的 JavaScript 變量并“按需”調用它上面的方法。這意味著任何 JavaScript 變量,無論它的定制程度多高,都可以從 Python 完整訪問。反過來也是沒問題的。
鴨子類型是一個原則,不是問變量“你是鴨子嗎?”而是問它“你像鴨子一樣走路嗎?”和“你像鴨子一樣嘎嘎叫嗎?”并從中推斷出它可能是一只鴨子, 或者至少像鴨子般行事。這使 Pyodide 可以延后決定如何轉換 JavaScript 對象:它將對象包裝在代理中,并讓使用它的 Python 代碼決定如何處理它。當然這招并不總能見效,因為你以為它是鴨子,實際上可能是一只兔子(https://www.illusionsindex.org/i/duck-rabbit)。因此 Pyodide 還提供了顯式處理這些轉換的方法:
https://github.com/iodide-project/pyodide/blob/master/docs/api_reference.md#pyodideas_nested_listobj
正是這種緊密的集成讓用戶可以在 Python 中處理數據,然后將其發送到 JavaScript 進行可視化。例如,在我們的 Hipster Band Finder 演示(https://alpha.iodide.io/notebooks/1623/)中,我們在 Python 的 Pandas 中加載和分析數據集,然后將其發送到 JavaScript 的 Plotly 進行可視化。
訪問 Web API 和 DOM代理也是訪問 Web API 的關鍵環節,或者是瀏覽器提供的使其能夠完成工作的一組功能。例如,Web API 的很大一部分位于 document 對象上。你可以這樣從 Python 中獲取它們:
from js import document這會將 JavaScript 中的 document 對象作為代理導入到 Python 端。你可以從 Python 開始調用它的方法:
document.getElementById("myElement")這些都是通過代理來查找 document 對象可以即時執行的操作。Pyodide 不需要包含瀏覽器所有 Web API 的完整列表。
當然,直接使用 Web API 并不會一直像大多數 Python 風格或者對用戶友好的方式那樣處理問題。我們希望能看到為 Web API 創建的對用戶友好的 Python 包裝器,就像 jQuery 之類的庫使 Web API 更容易通過 JavaScript 使用一樣。如果你想做這種工作,請告訴我們:
https://gitter.im/iodide-project/iodide
多維數組數據科學有自己特定的一些重要數據類型,Pyodide 也對它們提供了專門支持。其中,多維數組是所有相同類型(通常是數字)值的集合。它們往往很大,并且由于每個元素都是相同的類型,多維數組與可以容納任意類型元素的 Python 的 list 或 JavaScript 的 Array 相比,前者具有明顯的性能優勢。
在 Python 中,NumPy arrays 是多維數組的最流行實現。JavaScript 也有 TypedArrays,只包含一個數字類型,但它們是單維的,因此需要在其上構建多維索引。
由于實踐中這些數組可能會變得非常大,所以我們不希望在各個語言運行時之間復制它們。這不僅需要很長時間,而且在內存中同時存在兩個副本會對瀏覽器有限的可用內存造成負擔。
還好我們無需復制即可共享此數據。多維數組通常使用少量元數據來實現,這些元數據描述了值的類型、數組的形狀和內存布局。數據本身通過指向內存中另一個位置的指針從該元數據中引用。這部分內存位于一個稱為“WebAssembly 堆”的特殊區域,優點在于它既能用 JavaScript 也能用 Python 訪問。我們可以簡單地在語言之間來回復制元數據(元數據非常小),然后用指針指向引用 WebAssembly 堆的數據。
目前,這個想法是針對一維數組實現的,對于更高維數組而言,這是一個次優的解決方法。我們需要對 JavaScript 側進行改進,以便用一個有用的對象來處理它?,F在 JavaScript 多維數組還沒有很好的選擇。Apache Arrow 和 xnd 的 ndarray(https://xnd.io/)等有前景的項目正在研究這方面的問題,旨在使不同語言運行時之間的內存結構化數據的傳遞更加便利。我們正在研究如何利用這些項目,以進一步增強這種數據轉換操作。
實時交互式可視化如 Jupyter 所做的那樣,在瀏覽器中而不是在遠程內核中進行數據科學計算的優點之一是,交互式可視化不必通過網絡通信以重新處理和顯示其數據。這大大降低了延遲——也就是從用戶移動鼠標到更新繪圖顯示到屏幕所需的響應時間。
完成這項工作需要上述所有技術部分協同工作。先來看看這個交互式示例(https://alpha.iodide.io/notebooks/1658/),它使用 matplotlib 展示了對數正態分布的原理。首先,使用 Numpy 在 Python 中生成隨機數據;接下來 Matplotlib 獲取該數據,并使用其內置的軟件渲染器繪制它;它使用 Pyodide 對零拷貝數組共享的支持將像素發送回 JavaScript 端,最終將它們渲染到 HTML 畫布中。然后瀏覽器將這些像素顯示屏幕上。用于交互的鼠標和鍵盤事件由從 Web 瀏覽器調用的回調處理,發送回 Python。
打包Python 科學棧不是一個整體——它實際上是一組松散的附屬包,它們協同工作以打造生產環境。其中最受歡迎的是 NumPy(用于數值數組和基本計算)、Scipy(用于更復雜的通用計算,如線性代數),Matplotlib(用于可視化)和 Pandas(用于表格數據或“數據幀”)。可以在此處查看 Pyodide 為瀏覽器構建的完整包列表,該列表還在不斷更新:
https://github.com/iodide-project/pyodide/tree/master/packages
其中一些包很容易引入 Pyodide。通常來說,任何使用純 Python 編寫而沒有編譯語言擴展的東西都非常簡單。難度高一些的類別中,像 Matplotlib 這樣的項目需要使用特殊代碼在 HTML 畫布中顯示繪圖。有些包屬于極端困難的類型,其中 Scipy 就一直是一項巨大的挑戰。
Roman Yurchak 致力于將 Scipy 中的大量舊 Fortran 代碼編譯為 WebAssembly。Kirill Smelkov 改進了 emscripten,使共享對象可以被其他共享對象復用,從而縮小了 Scipy 的體積。(這些外部貢獻者的工作得到了 Nexedi,http://www.nexedi.com/ 的支持)。如果你正在努力將包移植到 Pyodide 上,請在 Github 上與我們聯系,你的問題我們之前很可能也遇到過:
https://github.com/iodide-project/pyodide/
由于我們無法預測用戶最終需要哪些包來完成任務,因此用戶可以根據需要將它們單獨下載到瀏覽器中。例如在導入 NumPy 時:
import numpy as npPyodide 會獲取 NumPy 庫(及其所有依賴項)并同時將它們加載到瀏覽器中。同樣,這些文件只需要下載一次,之后會存儲在瀏覽器的緩存中。
現在向 Pyodide 添加新包是一個半手動過程,其中需要向 Pyodide 中添加文件。長遠來看,我們更傾向于采用分布式方法解決這個問題,這樣任何人都可以無需處理單個項目就為生態系統貢獻包。這方面最好的例子是 conda-forge。如果能將它們的工具進一步擴展,支持 WebAssembly 作為平臺目標就好了,這樣就省去了很多重復勞動。
此外,Pyodide 很快將支持(https://github.com/iodide-project/pyodide/pull/147)直接從 PyPI(Python 的主社區包存儲庫,https://pypi.org/)加載包,只要它以純 Python 編寫并以輪格式(https://pythonwheels.com/)分發。這樣以來,Pyodide 現在就可以訪問大約 59,000 個包。
超越 PythonPyodide 較早期的成功已經激勵了其他語言,包括 Julia、R、OCaml、Lua 等社區的開發者,設法讓他們的語言運行時在瀏覽器中正常工作,并與 Iodide 等網絡優先工具集成。我們定義了一組級別,以鼓勵人們創建與 JavaScript 運行時聯系更緊密的集成:
第 1 級:只是字符串輸出,可以用作基本控制臺 REPL(read-eval-print-loop)。
第 2 級:將基本數據類型(數字、字符串、數組和對象)與 JavaScript 互相轉換。
第 3 級:在訪客語言和 JavaScript 之間共享類實例(帶方法的對象)。這樣就能允許 Web API 訪問了。
第 4 級:在訪客語言和 JavaScript 之間共享數據科學相關類型(n 維數組和數據幀)。
如果你尚未嘗試過 Pyodide,現在就試試吧:
https://alpha.iodide.io/notebooks/300/
原文鏈接https://hacks.mozilla.org/2019/04/pyodide-bringing-the-scientific-python-stack-to-the-browser/
今日薦文
點擊下方圖片即可閱讀
支付寶背后的OceanBase:國產自研分布式數據庫
活動推薦張鑫旭,資深前端工程師,《CSS 世界》作者,工作 10 年一直在專業一線,沒有管理任何人,但過得還不錯,在圈內也是小有名氣。我們來聽他聊聊工作 10 年以后,他在前端專業成長路上的探索。更多關于前端圈的最新技術干貨歡迎點擊“
總結
以上是生活随笔為你收集整理的无法扩展该卷 因为群集的数量将超过文件系统_浏览器将支持Python项目!Mozilla发布Pyodide...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: button 样式_缩减 SCSS 50
- 下一篇: 鸿蒙电脑操作系统最新消息,5G专家预测: