Obsah
1. JupyterLite – nová alternativní architektura Jupyter Notebooku
2. Architektura klasického Jupyter Notebooku
3. Architektura projektu JupyterLite
4. Ekosystém Pythonu běžící v prohlížeči nad Web Storage
6. Praktická část – příprava na instalaci projektu JupyterLite
7. Instalace potřebných balíčků
8. Sestavení statického webu s JupyterLite
9. Zobrazení uživatelského rozhraní JupyterLite v prohlížeči
10. Sledování interní činnosti projektu JupyterLite
12. Knihovny dostupné v základní instalaci projektu JupyterLite
15. Rychlost výpočtů v porovnání s nativním Jupyter Notebookem
16. Další možnosti projektu JupyterLite
17. Technologie WebAssembly (WASM)
18. Odkazy na články o Jupyter Notebooku
19. Odkazy na články a videa s tématem technologie WebAssembly
1. JupyterLite – nová alternativní architektura Jupyter Notebooku
S projektem Jupyter Notebook jsme se již na stránkách Roota několikrát setkali. Ukázali jsme si přitom jak práci s Pythonem, resp. přesněji řečeno s kernelem poskytujícím prostředí CPythonu, tak i s využitím Jupyter Notebooku společně s dalšími programovacími jazyky – konkrétně s Clojure, jazykem R, jazykem Go a v neposlední řadě taktéž s jazykem Hy.
Obrázek 1: Základní informace o projektu JupyterLite zobrazené přímo ve webovém prostředí.
Jednotlivé varianty se přitom odlišovaly „pouze“ výměnou kernelu, zatímco architektura Jupyter Notebooku zůstala stále stejná: kernel běží na straně serveru a o interakci s uživatelem se stará webová část. Toto řešení ovšem vyžaduje práci na straně serveru, zejména zabezpečení, nutnost zajistit dostatečný výpočetní výkon pro celou třídu (při výuce) atd. Existuje však i alternativní řešení, které spočívá v tom, že veškeré výpočty budou probíhat přímo na straně klienta, konkrétně v jeho webovém prohlížeči. A právě toto řešení je implementováno v projektu JupyterLite.
Obrázek 2: Úvodní obrazovka projektu JupyterLite při přístupu ke statickému obsahu z jiného počítače.
2. Architektura klasického Jupyter Notebooku
Připomeňme si ve stručnosti, jak vlastně vypadá architektura systému Jupyter Notebook; posléze si popíšeme odlišnosti mezi klasickým projektem Jupyter a Jupyterem Lite. Nástroj Jupyter Notebook je založen na klasické technologii klient-server, kde klientem je webový prohlížeč spuštěný u uživatele (či uživatelů) a serverem je Jupyter s přidaným modulem (takzvaným kernelem) pro zvolený programovací jazyk nebo jazyky. Výraz, popř. blok výrazů představujících programový kód napsaný ve zvoleném programovacím jazyce, je po stlačení klávesové zkratky Shift+Enter (v prostředí webového prohlížeče) přenesen na server, kde je zpracován a výsledek je poslán zpět do prohlížeče. Prakticky veškeré výpočty jsou tedy prováděny na straně serveru, který pochopitelně může běžet lokálně.
Obrázek 3: Nástroj Gorilla REPL obsahuje podporu pro doplňování názvů funkcí a maker společně se zobrazením nápovědy (programové dokumentace). Jedná se o nástroj založený na stejném paradigmatu jako dnes popisovaný Jupyter Notebook resp. JupyterLite, ovšem Gorilla REPL je primárně určen pro programovací jazyk Clojure zatímco Jupyter Notebook je více univerzální (původně vznikl pro Python, dnes podporuje cca třicet dalších jazyků).
JavaScriptový kód na straně prohlížeče zajistí interpretaci získaných výsledků a jejich zařazení na správné místo do dynamické webové stránky (jedná se vlastně o variantu na dnes tak populární SPA – Single-Page Application se všemi přednostmi a pochopitelně i některými zápory, které toto řešení přináší). Výsledky poslané serverem na klienta mohou být ve skutečnosti různého typu; typicky se jedná o fragment HTML (tabulky atd.), obrázek typu SVG (diagram, graf, histogram), rastrový obrázek (graf získaný například ze systému R), vzorec vykreslený z TeXového či LaTeXového zdrojového kódu, animace či video (různé formáty) apod. Samotná architektura nástroje Jupyter je přitom do značné míry otevřená a poměrně snadno rozšiřitelná, což znamená, že je v případě potřeby možné přidat například další typy grafů apod.
Obrázek 4: Dalším podobným projektem je R Markdown notebook, který je (jak již jeho název naznačuje) určený pro jazyk R zkombinovaný s Markdownem.
Zdroj: dokumentace k projektu dostupná na https://bookdown.org/yihui/rmarkdown/notebook.html
Jak jsme si již řekli v úvodní kapitole, vznikl projekt Jupyter Notebook rozšířením původního projektu nazvaného IPython Notebooks. V případě Jupyter Notebooku musely být provedeny některé změny v celé architektuře, a to především z toho důvodu, aby bylo možné podporovat různé programovací jazyky (nikoli pouze Python), další typy specializovaných kernelů apod. Základem je přitom stále IPython Kernel, který přijímá zprávy (příkazy, které se mají vykonat) přes ØMQ, vykonává tyto příkazy a výsledky posílá zpět přes ØMQ (povšimněte si, že v tomto případě samotný kernel vůbec nezajímá, kdo příkazy posílal):
Obrázek 5: IPython Kernel a jeho navázání na ØMQ (popř. alternativní přístup přes standardní vstupně-výstupní operace přístupné přes terminál).
Zdroj: How IPython and Jupyter Notebook work
IPython Kernel podporuje – což asi není při přečtení jeho jména velkým překvapením – programovací jazyk Python. Ovšem do Jupyter Notebooku lze přidat i další kernely (takzvané nativní kernely), které mohou podporovat další programovací jazyky. Alternativně není nutné vytvářet celý nový kernel (což může být komplikované kvůli nutnosti napojení na ØMQ atd.), ale lze použít přímo IPython Kernel tak, aby volal příkazy interpretru jiného programovacího jazyka. Teoreticky se sice nejedná o nejefektivnější řešení, ovšem musíme si uvědomit, že spouštěny budou příkazy zapisované přímo uživatelem a že tedy uživatel je „úzkým hrdlem“, ne výkonnost jednoho interpretru volaného z interpretru jiného:
Obrázek 6: Dva způsoby, jakými je možné Jupyter rozšířit o další jazyky: nepřímo přes IPython a přímo nativním kernelem.
Zdroj: How IPython and Jupyter Notebook work
Máme tedy dva moduly – webové rozhraní (webový prohlížeč s JSA) a kernel či kernely. Tyto dva moduly nejsou propojeny přímo, protože mezi nimi leží Notebook server. Ten z jedné strany komunikuje s webovým rozhraním přes HTTP a WebSockety a ze strany druhé s kernelem/kernely přes ØMQ. Navíc server udržuje stav vlastního diáře. Toto řešení je snadno rozšiřitelné, může být provozováno na jednom stroji (což si ukážeme dále) či v „cloudu“ atd. Taktéž umožňuje spolupráci na jednom diáři, prezentaci živých výsledků apod., což je naznačeno na dalším obrázku:
Obrázek 7: Připojení vlastního uživatelského rozhraní (založeného na webovém klientu) k serveru a propojení serveru s kernelem (kernely).
Zdroj: How IPython and Jupyter Notebook work
3. Architektura projektu JupyterLite
Projekt JupyterLite se z pohledu celkové architektury odlišuje od klasického Jupyter Notebooku. Namísto řešení typu klient-server, kdy jsou prakticky veškeré výpočty prováděny na straně serveru (který tak musí mít nainstalovány všechny potřebné kernely i příslušné knihovny), se v případě JupyterLite přenáší výkonná část (kernely, příslušné interpretry a knihovny) na stranu klienta. Ovšem jak toho lze dosáhnout, když klientem je v tomto případě webový prohlížeč? Jak kernely, tak i podporované interpretry (zejména Pythonu) je nutné upravit takovým způsobem, aby běžely přímo ve webovém prohlížeči. K vyřešení tohoto úkolu dnes existuje hned několik technologií:
- Využití takzvaných transpilerů (transpřekladačů, též transcompilers, source-to-source compilers), kdy cílem je JavaScript. Touto problematikou jsme se již na stránkách Rootu zabývali, a to dokonce několikrát. Transpřekladače jsou nástroje sloužící pro překlad algoritmů zapsaných v nějakém zdrojovém programovacím jazyce do zvoleného cílového jazyka (ovšem nikoli do nativního kódu či bajtkódu, to je totiž role běžných překladačů). Připomeňme si například projekty ClojureScript (transpřekladač Clojure → JavaScript), lua2js (transpřekladač Lua → opět JavaScript), Wisp (programovací jazyk podobný Clojure, opět překládaný na pozadí do JavaScriptu) i transpřekladač Coconut (ten ovšem nemá s JavaScriptem nic společného).
- Podobná technologie provádějící ovšem překlad do asm.js, tj. do striktně definované podmnožiny JavaScriptu. Podmnožina datových typů, konstrukcí jazyka, způsobů využití paměti (vše prováděno v předalokovaných polích) atd. je zvolena s ohledem na co největší výpočetní výkon výsledného skriptu – tj. jedná se o optimalizaci založenou na znalostech činnosti současných implementací JavaScriptu (V8 atd.).
- Reimplementace kernelu, interpretrů i knihoven v JavaScriptu. Příkladem využití může být projekt Brython, tj. reimplementace Pythonu pro webové prohlížeče. Ovšem reimplementace všech potřebných knihoven by byla dosti nepraktická, nehledě na problémy se zpětnou kompatibilitou atd..
- Lze použít i nástroj Emscripten umožňující překlad zdrojového kódu z libovolného jazyka podporovaného LLVM (Rust, C, C++, Objective C, D, Ada, Fortran atd.) do JavaScriptu nebo do WebAssembly (WASM). Právě projekt Emscripten do značné míry usnadnil další způsob zajištění běhu programů napsaných v různých programovacích jazycích ve webovém prohlížeči. Pokud je totiž možné přeložit jakýkoli program napsaný v jazycích C či C++ do JavaScriptu či WebAssembly (samozřejmě za předpokladu, že se vhodným způsobem budou emulovat použité knihovní funkce), proč by nebylo možné přeložit „pro web“ celý virtuální stroj používaný daným programovacím jazykem? Samozřejmě to možné je, a to zejména v těch případech, kdy je překládaný virtuální stroj (alespoň z dnešního pohledu) malý, což je příklad VM pro jazyk Lua, tak i například poněkud většího virtuálního stroje Pythonu (.NET resp. CLR či Java VM už je pochopitelně mnohem těžší oříšek).
4. Ekosystém Pythonu běžící v prohlížeči nad Web Storage
Konkrétně v případě projektu JupyterLite byla zvolena poslední zmíněná možnost, tedy překlad CPythonu (standardního interpretru Pythonu) i některých důležitých nativních knihoven (část NumPy) do WebAssembly (viz též sedmnáctou kapitolu). To však není vše, protože běžný interpret Pythonu používá příkazový řádek, dokáže pracovat se souborovým systémem atd. – tedy s technologiemi, které ve webovém prohlížeči buď v původní formě vlastně vůbec neexistují (příkazový řádek) nebo je naopak nechceme kvůli sandboxingu přímo využívat (přístup na souborový systém). Odstínění od těchto technologií je taktéž zajištěno, a to v rámci dále zmíněného projektu Pyodide. Výsledkem jsou binární soubory (pro WebAssembly), jejichž velikost je relativně velká – cca 22 MB pro Python a 7 MB pro NumPy. Tyto soubory, jak ostatně uvidíme dále, jsou staženy pouze jedenkrát, při prvním spuštění JupyterLite; posléze jsou již využity jejich cachované verze.
Jak je však zajištěna práce s vlastními diáři (notebook), když JupyterLite nemůže přímo přistupovat na souborový systém. Pro uložení všech dat se používá web storage (více informací je dostupných na stránce https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API) poskytovaná přímo webovým prohlížečem. Stále je pochopitelně možné diáře exportovat do běžných souborů a – jak uvidíme dále – lze dokonce vytvořit statický webový obsah s diáři, které si mohou uživatelé otevřít a lokálně upravit. Původní obsah diáře přitom zůstane zachován, což je téměř ideální situace například pro různá školení či prezentace.
Z pohledu uživatelů se tedy JupyterLite chová jako interaktivní webová aplikace, která si „pamatuje“ změny provedené v jednotlivých diářích – ve skutečnosti jsou tyto změny uloženy lokálně v paměti prohlížeče. A z pohledu administrátorů není JupyterLite nic jiného, než statický web, který na straně serveru vyžaduje libovolný web server (nginx, Apache HTTP atd.), nebo je dokonce možné celý web zveřejnit přes github.io, wiki či podobné nástroje. Pro sestavení tohoto statického webu se používají pomocné nástroje zmíněné v dalších kapitolách.
5. Projekt Pyodide
Nástroj JupyterLite je primárně postaven na projektu nazvaném Pyodide. Jedná se v prvé řadě o upravený překlad celého standardního Pythonu (konkrétně Pythonu 3.9) nikoli do nativního kódu spustitelného přímo z příkazové řádky, ale do WebAssembly, což znamená, že interpret Pythonu, resp. přesněji řečeno programů napsaných pro Python, lze spustit přímo z webového prohlížeče, a to dokonce bez nutnosti mít Python lokálně nainstalovaný – musíme mít pouze k dispozici vhodný webový server, stránky na github.io atd. Kromě toho je součástí projektu Pyodide i poměrně velké množství důležitých balíčků používaných ve vědeckotechnických výpočtech, zpracování numerických dat, statistických výpočtech, strojovém učení atd. Primárně se jedná o balíčky NumPy, Pandas, Matplotlib, SciPy a taktéž scikit-learn; s mnohými z nich jsme se ostatně na stránkách Roota již setkali. Seznam všech balíčků použitých v aktuální verzi Pyodide nalezneme na adrese https://github.com/pyodide/pyodide/tree/main/packages:
CLAPACK | Jinja2 | MarkupSafe | Pygments |
asciitree | astropy | atomicwrites | attrs |
autograd | beautifulsoup4 | biopython | bleach |
bokeh | cloudpickle | cssselect | cycler |
cytoolz | decorator | distlib | docutils |
freesasa | future | glpk | html5lib |
imageio | jedi | joblib | kiwisolver |
libiconv | libxml | libxslt | libyaml |
lxml | matplotlib | micropip | mne |
more-itertools | mpmath | msgpack | networkx |
nlopt | nltk | nose | numcodecs |
numpy | optlang | packaging | pandas |
parso | patsy | pillow | pluggy |
py | pyodide-interrupts | pyparsing | pyrtl |
pytest | python-dateutil | python-sat | pytz |
pywavelets | pyyaml | regex | retrying |
scikit-image | scikit-learn | scipy | setuptools |
six | soupsieve | statsmodels | swiglpk |
sympy | toolz | traits | typing-extensions |
uncertainties | webencodings | xlrd | yt |
zarr | zlib |
6. Praktická část – příprava na instalaci projektu JupyterLite
V praktické části dnešního článku si nejdříve ukážeme, jakým způsobem se nainstalují pomocné nástroje, které dokážou sestavit statický obsah webu s nástrojem (či možná lépe řečeno prostředím) JupyterLite a popř. i s předpřipravenými diáři neboli notebooky. Všechny přípravné operace budou prováděny na Fedoře 33 ve variantě server; pouze se doinstalovalo několik podpůrných balíčků – tar, git či wget. Konfigurace použitého serveru je následující (pro úplnost uvádím i příkazy, kterými se příslušné informace získaly):
$ cat /etc/fedora-release Fedora release 33 (Thirty Three)
$ uname -a Linux kvm-01-guest04.lab.eng.brq.redhat.com 5.12.15-200.fc33.x86_64 #1 SMP Wed Jul 7 19:56:49 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
$ python --version Python 3.9.6
$ pip --version pip 20.2.2 from /usr/lib/python3.9/site-packages/pip (python 3.9)
7. Instalace potřebných balíčků
Jak jsme si již řekli v předchozím textu, používá se pro sestavení statického obsahu webu podpůrný nástroj. Ten je možné nainstalovat přímo z PyPi, a to konkrétně následujícím příkazem:
$ pip install --user --pre jupyterlite Collecting jupyterlite Downloading jupyterlite-0.1.0a5-py3-none-any.whl (20.1 MB) |████████████████████████████████| 20.1 MB 2.6 MB/s Collecting doit Downloading doit-0.33.1-py3-none-any.whl (84 kB) |████████████████████████████████| 84 kB 4.7 MB/s Collecting jupyter_core>=4.7 Downloading jupyter_core-4.7.1-py3-none-any.whl (82 kB) |████████████████████████████████| 82 kB 1.5 MB/s Collecting entrypoints Downloading entrypoints-0.3-py2.py3-none-any.whl (11 kB) Collecting pyinotify; sys_platform == "linux" Downloading pyinotify-0.9.6.tar.gz (60 kB) |████████████████████████████████| 60 kB 7.1 MB/s Collecting cloudpickle Downloading cloudpickle-1.6.0-py3-none-any.whl (23 kB) Collecting traitlets Downloading traitlets-5.0.5-py3-none-any.whl (100 kB) |████████████████████████████████| 100 kB 11.1 MB/s Collecting ipython-genutils Downloading ipython_genutils-0.2.0-py2.py3-none-any.whl (26 kB) Using legacy 'setup.py install' for pyinotify, since package 'wheel' is not installed. Installing collected packages: pyinotify, cloudpickle, doit, ipython-genutils, traitlets, jupyter-core, entrypoints, jupyterlite Running setup.py install for pyinotify ... done Successfully installed cloudpickle-1.6.0 doit-0.33.1 entrypoints-0.3 ipython-genutils-0.2.0 jupyter-core-4.7.1 jupyterlite-0.1.0a5 pyinotify-0.9.6 traitlets-5.0.5
Tento nástroj dokáže na základě specifikované konfigurace sestavit obsah statického webu, který zajistí možnost spuštění JupyterLite uživateli. Pokud ovšem mají být k dispozici i předpřipravené diáře, je nutné mít při sestavování statického webu nainstalován ještě jeden balíček:
$ pip3 install --user jupyter_server Collecting jupyter_server Downloading jupyter_server-1.9.0-py3-none-any.whl (389 kB) |████████████████████████████████| 389 kB 2.8 MB/s Collecting nbformat Downloading nbformat-5.1.3-py3-none-any.whl (178 kB) |████████████████████████████████| 178 kB 3.8 MB/s Requirement already satisfied: ipython-genutils in /home/tester/.local/lib/python3.9/site-packages (from jupyter_server) (0.2.0) Collecting Send2Trash Downloading Send2Trash-1.7.1-py3-none-any.whl (17 kB) ... ... ... Running setup.py install for pandocfilters ... done Successfully installed MarkupSafe-2.0.1 Send2Trash-1.7.1 anyio-3.2.1 argon2-cffi-20.1.0 async-generator-1.10 attrs-21.2.0 bleach-3.3.1 certifi-2021.5.30 cffi-1.14.6 charset-normalizer-2.0.3 defusedxml-0.7.1 idna-3.2 jinja2-3.0.1 jsonschema-3.2.0 jupyter-client-6.1.12 jupyter-server-1.9.0 jupyterlab-pygments-0.1.2 mistune-0.8.4 nbclient-0.5.3 nbconvert-6.1.0 nbformat-5.1.3 nest-asyncio-1.5.1 packaging-21.0 pandocfilters-1.4.3 prometheus-client-0.11.0 ptyprocess-0.7.0 pycparser-2.20 pygments-2.9.0 pyparsing-2.4.7 pyrsistent-0.18.0 pyzmq-22.1.0 requests-2.26.0 requests-unixsocket-0.2.0 sniffio-1.2.0 terminado-0.10.1 testpath-0.5.0 tornado-6.1 urllib3-1.26.6 webencodings-0.5.1 websocket-client-1.1.0
8. Sestavení statického webu s JupyterLite
V této chvíli by měly být k dispozici všechny potřebné nástroje nutné pro sestavení statického webu, který sám o sobě zajistí uživatelům přístup k JupyterLite, a to s využitím prakticky jakéhokoli webového serveru – ten pouze musí umět poskytovat statické soubory; nemusí již umět spouštět skripty ani žádný middleware.
Takový statický web připravíme příkazem:
$ jupyter lite init static:jupyter-lite.json . pre_status:static:jupyter-lite.json tarball: jupyterlite-app-0.1.0-alpha.5.tgz 19MB output: /home/tester/_output lite dir: /home/tester apps: ('lab', 'retro') archive:archive contents:contents lite:jupyter-lite.json serve:contents settings:overrides . status:archive:archive [LiteInitApp] No archive (yet): tester-jupyterlite.tgz . status:contents:contents contents: 0 files . status:lite:jupyter-lite.json [LiteInitApp] jupyter-lite.(json|ipynb): 0 files . status:serve:contents will serve 8000 with: stdlib . status:settings:overrides overrides.json: 0 static:output_dir . pre_init:static:output_dir static:unpack . init:static:unpack
Po dokončení tohoto příkazu by měl být vytvořen podadresář _output obsahující kýžený obsah statického webu. Můžeme se tedy pokusit spustit webový server (ten nejjednodušší, který navíc již v systému je nainstalován) a posléze na server přistoupit z jiného počítače. Přepneme se do vytvořeného podadresáře:
$ cd _output
A spustíme webový server:
$ python -m http.server Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
9. Zobrazení uživatelského rozhraní JupyterLite v prohlížeči
Ve chvíli, kdy webový server dodávající statický obsah běží, se můžeme ve webovém prohlížeči (ten může být provozován na jiném počítači) připojit na port :8000. Měla by se zobrazit stránka se standardním uživatelským rozhraním nástroje JupyterLite, která vypadá následovně:
Obrázek 8: Úvodní stránka se standardním uživatelským rozhraním JupyterLite.
V případě, že na konec adresy doplníme ještě část „/retro“ (bez uvozovek), zobrazí se poněkud odlišná stránka, která odpovídá původnímu designu JupyterNotebooku popř. IPython Notebooku:
Obrázek 9: Úvodní stránka s původním uživatelským rozhraním Jupyter Notebooku či IPython Notebooku.
Po funkční stránce jsou obě stránky prakticky rovnocenné. Můžeme z nich otevřít existujující diáře (popíšeme si v dalším textu) nebo vytvořit diář nový výběrem příslušného kernelu (Pyolite):
Obrázek 10: Nový diář otevřený v rámci projektu JupyterLite.
10. Sledování interní činnosti projektu JupyterLite
Při otevírání prvního diáře je vhodné si nechat zobrazit vývojovou konzoli, konkrétně list Network. V něm se zobrazí všechny soubory stahované jak z našeho serveru se statickým obsahem, tak i z dalších serverů. Mj. se stahuje i celý přeložený Pyodide:
Obrázek 11: Při prvním otevírání diáře se stahuje přibližně stovka souborů.
Po otevření diáře (či více diářů) se tyto uloží do lokální paměti webového prohlížeče. Velikost uložených dat je pochopitelně možné taktéž zobrazit:
Obrázek 12: Dva diáře společně s dalšími kontextovými daty zabraly přibližně 450 kB.
A konečně je možné na speciální stránce s adresou about:performance sledovat objem alokované paměti a (přibližné) vytížení procesoru:
Obrázek 13: Sledování alokovaného objemu paměti a taktéž vytížení procesoru jednotlivými stránkami otevřenými ve webovém prohlížeči.
11. Server s vlastními diáři
Dalším krokem při nasazování nástroje JupyterLite na server je přidání vlastních diářů (notebooků), které si budou moci uživatelé otevřít, prohlížet, spouštět jednotlivé příkazy a popř. je i upravovat. Veškeré úpravy ovšem budou pouze lokální a platné v rámci prohlížeče uživatelů, protože zpětný zápis diáře na server není (takto jednoduše) možný – což ostatně přesně odpovídá tomu, proč se vlastně JupyterLite používá, tedy pro přenesení všech výpočtů na stranu klienta.
Příprava diářů je jednoduchá, protože je postačuje umístit do nějakého adresáře a následně spustit nám již známý příkaz jupyter lite build, ovšem navíc se specifikací adresáře či adresářů s diáři.
Nejprve naklonujeme repositář s množstvím připravených diářů:
$ git clone http://github.com/tisnik/jupyter-notebook-examples.git Cloning into 'jupyter-notebook-examples'... warning: redirecting to https://github.com/tisnik/jupyter-notebook-examples.git/ remote: Enumerating objects: 643, done. remote: Counting objects: 100% (643/643), done. remote: Compressing objects: 100% (366/366), done. remote: Total 643 (delta 301), reused 606 (delta 267), pack-reused 0 Receiving objects: 100% (643/643), 7.11 MiB | 9.93 MiB/s, done. Resolving deltas: 100% (301/301), done.
V dalším kroku si necháme připravit statický web i s těmito diáři:
$ cd jupyter-notebook-examples/ $ jupyter lite build --files . static:jupyter-lite.json . pre_status:static:jupyter-lite.json tarball: jupyterlite-app-0.1.0-alpha.5.tgz 19MB output: /home/tester/work2/jupyter-notebook-examples/_output lite dir: /home/tester/work2/jupyter-notebook-examples apps: ('lab', 'retro') archive:archive contents:contents lite:jupyter-lite.json serve:contents settings:overrides . status:archive:archive [LiteBuildApp] No archive (yet): jupyter-notebook-examples-jupyterlite.tgz . status:contents:contents contents: 196 files . status:lite:jupyter-lite.json [LiteBuildApp] jupyter-lite.(json|ipynb): 0 files . status:serve:contents will serve 8000 with: tornado . status:settings:overrides overrides.json: 0 static:output_dir . pre_init:static:output_dir static:unpack . init:static:unpack contents:copy:/files/Clojupyter - BufferedBitmap.ipynb contents:copy:/files/Clojupyter - Importing clojure.repl namespace.ipynb ... ... ... contents:contents:clojupyter-project/test/xyz contents:contents:. federated_extensions:patch . post_build:contents:contents:R . post_build:contents:contents:calysto_hy . post_build:contents:contents:clojupyter . post_build:contents:contents:clojupyter-project . post_build:contents:contents:courses . post_build:contents:contents:docs . post_build:contents:contents:matplotlib . post_build:contents:contents:pandas . post_build:contents:contents:push-pull-model-benchmarks . post_build:contents:contents:raster_images . post_build:contents:contents:clojupyter-project/doc . post_build:contents:contents:clojupyter-project/src . post_build:contents:contents:clojupyter-project/test . post_build:contents:contents:clojupyter-project/src/xyz . post_build:contents:contents:clojupyter-project/test/xyz . post_build:contents:contents:. . post_build:federated_extensions:patch
Výsledkem činnosti tohoto příkazu bude nový podadresář, který je implicitně pojmenovaný _output. V něm je opět umístěna kostra celého JupyterLite, ovšem navíc jsou do něho umístěny i diáře.
Opět spustíme HTTP server nad daným podadresářem _output (původní HTTP server je nutné buď zastavit, nebo použít odlišný port):
$ cd _output $ python -m http.server Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Po otevření webového prostředí by se měl adresář či adresáře s diáři zobrazit v nabídce:
Obrázek 14: Adresář s diáři zobrazený v novém webovém prostředí.
Obrázek 15: Seznam připravených diářů v novém webovém prostředí.
To samé ostatně platí i při použití původního uživatelského prostředí Jupyter Notebooku (povšimněte si odlišné adresy):
Obrázek 16: Adresář s diáři zobrazený v původním webovém prostředí.
Obrázek 17: Seznam připravených diářů v původním webovém prostředí.
12. Knihovny dostupné v základní instalaci projektu JupyterLite
Nyní, když máme k dispozici sadu diářů připravených pro různé účely, si můžeme vyzkoušet, které knihovny jsou v nástroji JupyterLite dostupné. Prozatím se stále budeme soustředit na využití programovacího jazyka Python – možnosti nabízené JavaScriptem alespoň v kontextu tohoto článku nebudeme zmiňovat, protože se JavaScriptem (a především jeho knihovnami) v prostředí Jupyteru budeme zabývat v samostatném článku.
Pochopitelně je k dispozici základní knihovna Pythonu, s výjimkou těch funkcí, které vyžadují specifické vlastnosti poskytované operačním systémem, jež nemají svoji variantu dostupnou v prostředí webového prohlížeče. Ovšem v rámci projektu Pyodide byly přidány i další knihovny, resp. přesněji řečeno jejich verze přeložené pro WebAssembly – a tato „maličkost“ je důležitá zejména v kontextu knihovny NumPy, jejíž webová varianta zdaleka nedosahuje výpočetní rychlosti varianty nativní.
Obrázek 18: Problémy podle očekávání nastávají při pokusu o práci s lokálními soubory.
13. NumPy
K dispozici je ovšem knihovna NumPy, která je v komunitě Jupyter Notebooku velmi často používaná. Pochopitelně muselo dojít k překladu původně nativních částí této knihovny do WebAssembly, což mj. znamená zpomalení výpočtů. Nicméně tato knihovna je stále velmi dobře použitelná.
Obrázek 19: Společné použití knihoven NumPy a Matplotlib.
14. Matplotlib
Využít lze i knihovnu Matplotlib, ovšem za předpokladu, že jsou grafy přímo zobrazeny v ploše webového prohlížeče. Pokud se ovšem používá funkce plg.savefig() pro uložení obrázku s grafem na disk, nebudou tyto obrázky uloženy na souborový systém (což je vlastně dobře, protože prohlížeč zde nabízí sandboxing).
Obrázek 20: Společné použití knihoven NumPy a Matplotlib.
15. Rychlost výpočtů v porovnání s nativním Jupyter Notebookem
Při spouštění výpočtů v JupyterLite je nutné se připravit na to, že některé výpočty budou pomalejší, a to mnohdy značně. Následující příklad tento rozdíl ukazuje. Jedná se o relativně pomalý výpočet nad NumPy polem. JupyterLite tento výpočet dokončil za 2 minuty a 22 sekund, zatímco kernel založený na CPythonu ten stejný výpočet dokončil za 20 sekund:
Obrázek 21: Výpočet v JupyterLite trval 2 minuty 22 sekund.
Obrázek 22: Stejný výpočet, ovšem spuštěný z klasického Jupyter Notebooku, trval pouze 20 sekund.
Větší budou i paměťové nároky, což je (pro ty stejné výpočty) ukázáno na dvou výstupech utility top:
Obrázek 23: Paměťové nároky moderních webových prohlížečů jsou mnohdy obrovské; v tomto případě kvůli běhu JupyterLite.
Obrázek 24: Na druhou stranu jsou paměťové nároky CPython kernelu relativně malé.
16. Další možnosti projektu JupyterLite
Kromě diářů dokáže JupyterLite do statického webového obsahu přidat i obrázky, dokumenty apod. a (teoreticky) ho lze využít pro tvorbu ucelených webových stránek (diáře založené na Markdownu). Výstup z JupyterLite (tedy statický obsah) lze v plné funkcionalitě uložit na github.io, o čemž se ostatně můžete snadno přesvědčit na adrese https://jupyterlite.github.io/demo/lab/. A konečně dokáže JupyterLite přidat do tvořeného statického webu i další aplikace, kernely, doplňky daného ekosystému atd. Tyto možnosti budou představeny v navazujícím článku.
Obrázek 25: Složitější výpočty a vizualizace podivných atraktorů v nástroji JupyterLite.
17. Technologie WebAssembly (WASM)
V předchozím textu jsme se již několikrát zmínili o technologii nazvané WebAssembly či zkráceně pouze WASM. V první řadě se jedná o specifikaci virtuálního stroje, především jeho struktury (pro zajímavost: je založen na zásobníku operandů, podobně jako například virtuální stroj Javy) a taktéž ze specifikace jeho instrukčního souboru. Důležité přitom je, že současně používaná varianta WebAssembly je skutečně dosti nízkoúrovňová, takže (alespoň prozatím) neobsahuje například ani podporu pro automatickou správu paměti a i specifikace samotného runtime je dosti minimalistická. To je ovšem v mnoha ohledech nutno chápat jako přednost, protože u programovacích jazyků typu C, C++ či Rust není automatická správa paměti relevantní a jejich runtime je malý a naopak u jazyků typu Go je správce paměti přímo součástí runtime (zjednodušeně řečeno knihoven, které jsou slinkovány a tvoří výsledný bajtkód předávaný WebAssembly). Správa paměti řízená přímo WebAssembly je prozatím ve fázi vývoje a dnes ji nebudeme potřebovat ani si ji popisovat.
Již v předchozím odstavci jsme se zmínili o problematice runtime. Virtuální stroj WebAssembly akceptuje soubory s MIME typem nastaveným na application/wasm, které by měly obsahovat jak vlastní kód aplikace přeložený do bajtkódu, tak i veškerý podpůrný kód. V případě (například) programovacího jazyka Go to konkrétně znamená, že soubory s přeloženou aplikací jsou poměrně velké. I ta nejjednodušší aplikace přeložená do WebAssembly má velikost cca 1300 kB, protože je ve výsledku obsažený celý potřebný runtime i automatický správce paměti. A v případě Pythonu – viz předchozí kapitoly – je velikost runtime ještě o mnoho větší, což znamená, že první načtení celého podpůrného prostředí pro Jupyter Notebooky bude v případě Jupyteru Lite trvat delší dobu. Další spuštění již budou příslušné WASM soubory načítat z lokální diskové cache, takže inicializace celého prostředí by měla být prakticky okamžitá – řádově v sekundách, i méně.
Předností WebAssembly v porovnání s dalšími webovými technologiemi (transpilery, asm.js) by měla být větší rychlost provádění přeloženého kódu, která by s kvalitním just-in-time překladačem mohla dosahovat podobného výkonu jako nativní kód. A nesmíme zapomenout ani na fakt, že do WebAssembly lze překládat z mnoha běžných mainstreamových jazyků, například z C, C++, Go, Rustu atd. Pro Go je k dispozici vlastní překladač, pro ostatní zmíněné jazyky lze použít Emscripten.
18. Odkazy na články o Jupyter Notebooku
Se samotným nástrojem Jupyter Notebook jsme se již na stránkách Rootu čtyřikrát setkali, a to konkrétně v následujících článcích:
- Jupyter Notebook – nástroj pro programátory, výzkumníky i lektory
https://www.root.cz/clanky/jupyter-notebook-nastroj-pro-programatory-vyzkumniky-i-lektory/ - Tvorba grafů v Jupyter Notebooku s využitím knihovny Matplotlib
https://www.root.cz/clanky/tvorba-grafu-v-jupyter-notebooku-s-vyuzitim-knihovny-matplotlib/ - Tvorba grafů v Jupyter Notebooku s využitím knihovny Matplotlib (dokončení)
https://www.root.cz/clanky/tvorba-grafu-v-jupyter-notebooku-s-vyuzitim-knihovny-matplotlib-dokonceni/ - Jupyter Notebook – operace s rastrovými obrázky a UML diagramy, literate programming
https://www.root.cz/clanky/jupyter-notebook-operace-s-rastrovymi-obrazky-a-uml-diagramy-literate-programming/ - Interpret programovacího jazyka Clojure integrovaný do Jupyter Notebooku
https://www.root.cz/clanky/interpret-programovaciho-jazyka-clojure-integrovany-do-jupyter-notebooku/ - Calysto Hy: integrace programovacího jazyka Hy s Jupyter Notebookem
https://www.root.cz/clanky/calysto-hy-integrace-programovaciho-jazyka-hy-s-jupyter-notebookem/
19. Odkazy na články a videa s tématem technologie WebAssembly
- Využití WebAssembly z programovacího jazyka Go
https://www.root.cz/clanky/vyuziti-webassembly-z-programovaciho-jazyka-go/ - WebAssembly prošlo standardizací ve W3C, byla vydána verze 1.0
https://www.root.cz/zpravicky/webassembly-proslo-standardizaci-ve-w3c-byla-vydana-verze-1–0/ - WebAssembly
https://webassembly.org/ - WebAssembly na Wiki Golangu
https://github.com/golang/go/wiki/WebAssembly - The future of WebAssembly – A look at upcoming features and proposals
https://blog.scottlogic.com/2018/07/20/wasm-future.html - Writing WebAssembly By Hand
https://blog.scottlogic.com/2018/04/26/webassembly-by-hand.html - WebAssembly Specification
https://webassembly.github.io/spec/core/index.html - Index of Instructions
https://webassembly.github.io/spec/core/appendix/index-instructions.html - The WebAssembly Binary Toolkit
https://github.com/WebAssembly/wabt - Will WebAssembly replace JavaScript? Or Will WASM Make JavaScript More Valuable in Future?
https://dev.to/vaibhavshah/will-webassembly-replace-javascript-or-will-wasm-make-javascript-more-valuable-in-future-5c6e - Roadmap (pro WebAssemly)
https://webassembly.org/roadmap/ - S-expression
https://en.wikipedia.org/wiki/S-expression - Understanding WebAssembly text format
https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format - Learning Golang through WebAssembly – Part 1, Introduction and setup
https://www.aaron-powell.com/posts/2019–02–04-golang-wasm-1-introduction/ - Learning Golang through WebAssembly – Part 2, Writing your first piece of Go
https://www.aaron-powell.com/posts/2019–02–05-golang-wasm-2-writing-go/ - Learning Golang through WebAssembly – Part 3, Interacting with JavaScript from Go
https://www.aaron-powell.com/posts/2019–02–06-golang-wasm-3-interacting-with-js-from-go/ - Golang webassembly (wasm) testing with examples
https://jelinden.fi/blog/golang-webassembly-wasm-testing-with-examples/qB7Tb2KmR - Use Cases (of WebAssembly)
https://webassembly.org/docs/use-cases/ - Tabulka s podporou WebAssembly v různých prohlížečích
https://caniuse.com/#feat=wasm - An introduction to WebAssembly
https://www.youtube.com/watch?v=3sU557ZKjUs - Web Assembly (WASM) in 100 Seconds
https://www.youtube.com/watch?v=cbB3QEwWMlA - What is WebAssembly?
https://www.youtube.com/watch?v=kTZoZbxDudw
20. Další odkazy na Internetu
- JupyterLite na PyPi
https://pypi.org/project/jupyterlite/ - JupyterLite na GitHubu
https://github.com/jupyterlite/jupyterlite - Dokumentace k projektu JupyterLite
https://github.com/jupyterlite/jupyterlite - Notebook interface
https://en.wikipedia.org/wiki/Notebook_interface - Jypyter: open source, interactive data science and scientific computing across over 40 programming languages
https://jupyter.org/ - Matplotlib Home Page
http://matplotlib.org/ - Matplotlib (Wikipedia)
https://en.wikipedia.org/wiki/Matplotlib - Popis barvových map modulu matplotlib.cm
https://gist.github.com/endolith/2719900#id7 - Ukázky (palety) barvových map modulu matplotlib.cm
http://matplotlib.org/examples/color/colormaps_reference.html - Galerie grafů vytvořených v Matplotlibu
https://matplotlib.org/3.2.1/gallery/ - showcase example code: xkcd.py
https://matplotlib.org/xkcd/examples/showcase/xkcd.html - Customising contour plots in matplotlib
https://philbull.wordpress.com/2012/12/27/customising-contour-plots-in-matplotlib/ - Graphics with Matplotlib
http://kestrel.nmt.edu/~raymond/software/python_notes/paper004.html - The IPython Notebook
http://ipython.org/notebook.html - nbviewer: a simple way to share Jupyter Notebooks
https://nbviewer.jupyter.org/ - Back to the Future: Lisp as a Base for a Statistical Computing System
https://www.stat.auckland.ac.nz/~ihaka/downloads/Compstat-2008.pdf - gg4clj: a simple wrapper for using R's ggplot2 in Clojure and Gorilla REPL
https://github.com/JonyEpsilon/gg4clj - Analemma: a Clojure-based SVG DSL and charting library
http://liebke.github.io/analemma/ - Clojupyter: a Jupyter kernel for Clojure
https://github.com/roryk/clojupyter - Incanter is a Clojure-based, R-like platform for statistical computing and graphics.
http://incanter.org/ - Evolution of incanter (Gource Visualization)
https://www.youtube.com/watch?v=TVfL5nPELr4 - Questions tagged [incanter] (na Stack Overflow)
https://stackoverflow.com/questions/tagged/incanter?sort=active - Data Sorcery with Clojure
https://data-sorcery.org/contents/ - What is REPL?
https://pythonprogramminglanguage.com/repl/ - What is a REPL?
https://codewith.mu/en/tutorials/1.0/repl - Programming at the REPL: Introduction
https://clojure.org/guides/repl/introduction - What is REPL? (Quora)
https://www.quora.com/What-is-REPL - Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/ - R Markdown: The Definitive Guide
https://bookdown.org/yihui/rmarkdown/ - Single-page application
https://en.wikipedia.org/wiki/Single-page_application - Video streaming in the Jupyter Notebook
https://towardsdatascience.com/video-streaming-in-the-jupyter-notebook-635bc5809e85 - How IPython and Jupyter Notebook work
https://jupyter.readthedocs.io/en/latest/architecture/how_jupyter_ipython_work.html - Jupyter kernels
https://github.com/jupyter/jupyter/wiki/Jupyter-kernels - Keras: The Python Deep Learning library
https://keras.io/ - TensorFlow
https://www.tensorflow.org/ - PyTorch
https://pytorch.org/ - Seriál Torch: framework pro strojové učení
https://www.root.cz/serialy/torch-framework-pro-strojove-uceni/ - Scikit-learn
https://scikit-learn.org/stable/ - Java Interop (Clojure)
https://clojure.org/reference/java_interop - Obrazy s balíčky Jupyter Notebooku pro Docker
https://hub.docker.com/u/jupyter/#! - Správce balíčků Conda (dokumentace)
https://docs.conda.io/en/latest/ - Lorenzův atraktor
https://www.root.cz/clanky/fraktaly-v-pocitacove-grafice-vi/#k02 - Lorenzův atraktor
https://www.root.cz/clanky/fraktaly-v-pocitacove-grafice-iii/#k03 - Graphics with Matplotlib
http://kestrel.nmt.edu/~raymond/software/python_notes/paper004.html - Embedding Matplotlib Animations in Jupyter Notebooks
http://louistiao.me/posts/notebooks/embedding-matplotlib-animations-in-jupyter-notebooks/ - Literate programing, Kolokviální práce Pavla Starého
https://www.fi.muni.cz/usr/jkucera/pv109/starylp.htm - PlantUML (home page)
http://plantuml.sourceforge.net/ - PlantUML (download page)
http://sourceforge.net/projects/plantuml/files/plantuml.jar/download - PlantUML (Language Reference Guide)
http://plantuml.sourceforge.net/PlantUML_Language_Reference_Guide.pdf - Plain-text diagrams take shape in Asciidoctor!
http://asciidoctor.org/news/2014/02/18/plain-text-diagrams-in-asciidoctor/ - Graphviz – Graph Visualization Software
http://www.graphviz.org/ - graphviz (Manual Page)
http://www.root.cz/man/7/graphviz/ - PIL: The friendly PIL fork (home page)
https://python-pillow.org/ - Python Imaging Library (PIL), (home page)
http://www.pythonware.com/products/pil/ - PIL 1.1.6 na PyPi
https://pypi.org/project/PIL/ - Pillow 5.2.0 na PyPi
https://pypi.org/project/Pillow/ - Python Imaging Library na Wikipedii
https://en.wikipedia.org/wiki/Python_Imaging_Library - Pillow na GitHubu
https://github.com/python-pillow/Pillow - Pillow – dokumentace na readthedocs.io
http://pillow.readthedocs.io/en/5.2.x/ - How to use Pillow, a fork of PIL
https://www.pythonforbeginners.com/gui/how-to-use-pillow - Pyodide
https://github.com/pyodide/pyodide - Deploying
https://jupyterlite.readthedocs.io/en/latest/deploying.html - Pyodide: Bringing the scientific Python stack to the browser
https://hacks.mozilla.org/2019/04/pyodide-bringing-the-scientific-python-stack-to-the-browser/ - Dan Callahan – Keynote – PyCon 2018
https://www.youtube.com/watch?v=ITksU31c1WY - Web Storage API
https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API