Hlavní navigace

PyScript: Python ve webovém prohlížeči (dokončení)

27. 9. 2022
Doba čtení: 34 minut

Sdílet

 Autor: Depositphotos
Nejprve dokončíme část věnovanou tvorbě grafů s využitím knihovny Matplotlib, pak si řekneme, jak do stránky vložit plnohodnotný REPL Pythonu a v závěru si ukážeme provázání mezi aktivními prvky webové stránky a skripty v Pythonu.

Obsah

1. PyScript: další technologie umožňující využití Pythonu ve webovém browseru (dokončení)

2. Složitější graf vykreslený knihovnou Matplotlib: kontury funkce z=f(x,y)

3. Zobrazení grafu s konturami funkce na ploše webové stránky

4. Zobrazení 3D grafu s průběhem funkce z=f(x,y)

5. 3D graf vykreslený na ploše webové stránky

6. Změna velikosti obrázku s grafem

7. Pythonovská interaktivní smyčka REPL přímo na ploše webové stránky

8. REPL bez předvyplněného obsahu (základní podoba značky py-repl)

9. Vstupní prvek smyčky REPL s předvyplněným obsahem

10. Interaktivní vykreslování grafů na webové stránce

11. Interaktivní změna parametrů zobrazovaných funkcí

12. Reakce na události: zavolání funkce naprogramované v Pythonu po stisku tlačítka

13. Propojení události s Pythonovským kódem přes proxy

14. Přečtení hodnoty uložené v interaktivním prvku webové stránky

15. Zobrazení grafu po stisku tlačítka na webové stránce

16. Interaktivní prvky pro zadání amplitudy, frekvence a posunutí zobrazované funkce

17. Úprava předchozího demonstračního příkladu – reakce na nesprávné vstupy

18. Závěrečné zhodnocení

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. PyScript: další technologie umožňující využití Pythonu ve webovém browseru (dokončení)

Na úvodní článek o projektu PyScript, který umožňuje přímo do webových stránek vkládat kód zapsaný v Pythonu, dnes navážeme. Nejprve dokončíme část věnovanou tvorbě grafů s využitím knihovny Matplotlib a následně si ukážeme použití nové značky nazvané py-repl, která umožňuje vložit do plochy webové stránky Pythonovskou interaktivní smyčku REPL, což mnohdy znamená velkou podporu; například se nemusí tolik investovat do GUI formulářů (navíc může být vstup již předvyplněn nebo je možné do stránky vložit větší množství REPLů). Ovšem skripty psané v Pythonu musí nějakým způsobem komunikovat přímo s webovou stránkou i reagovat na akce prováděné uživatelem (tedy musí reagovat na události). Zde je již nutné alespoň do určité míry využít JavaScript a propojit tak zdroj události s Pythonovskou funkcí přes takzvanou proxy.

Obrázek 1: Graf vykreslený přímo do plochy HTML stránky – využití Pythonu, NumPy a Matplotlibu.

2. Složitější graf vykreslený knihovnou Matplotlib: kontury funkce z=f(x,y)

První způsob zobrazení funkce typu z=f(x,y) spočívá ve vykreslení takzvaných kontur, které si pro zjednodušení můžeme představit jako vrstevnice na mapě – body spojené konturou/vrstevnicí mají stejnou hodnotu funkce (tj. stejnou hodnotu z-ové souřadnice; řekněme výšky). Při vyhodnocování a následném vykreslení funkce budeme postupovat následovně:

  1. Vytvoříme vektor s hodnotami nezávislé proměnné x.
  2. Vytvoříme vektor s hodnotami nezávislé proměnné y.
  3. S využitím funkce numpy.meshgrid necháme vygenerovat dvojici matic souřadnic [x,y].
  4. Necháme vypočítat body ležící na ploše funkce (z-ové souřadnice se uloží do matice Z).
  5. Vlastní vykreslení kontur zajistí funkce matplotlib.pyplot.contour(X, Y, Z).

Skript zapsaný v čistém Pythonu by mohl vypadat následovně:

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
 
 
delta  = 0.1
 
# průběh nezávislé  proměnné  x
x  =  np.arange(-10.0,  10.0, delta)
 
# průběh nezávislé proměnné y
y  =  np.arange(-10.0,  10.0,delta)
 
# vytvoření dvou polí se souřadnicemi [x,y]
X, Y = np.meshgrid(x,  y)
 
# vzdálenost od bodu [0,0]
R1 = np.sqrt(X*X+Y*Y)
 
# vzdálenost od bodu [3,3]
R2 = np.sqrt((X-3)*(X-3)+(Y-3)*(Y-3))
 
# výpočet funkce, kterou použijeme při vykreslování grafu
Z = np.sin(R1)-np.cos(R2)
 
# povolení zobrazení mřížky
plt.grid(True)
 
# vytvoření grafu s konturami funkce z=f(x,y)
plt.contour(X, Y, Z)
 
# zobrazení grafu
plt.show()
graf

Obrázek 2: Výsledný graf.

graf

Obrázek 3: V případě, že je hodnota „delta“ příliš vysoká, vypočte se menší počet bodů tvořících plochu funkce, takže i kontury budou vykresleny velmi nepřesně (knihovna bude mít k dispozici jen málo bodů, které bude moci spojit).

3. Zobrazení grafu s konturami funkce na ploše webové stránky

Skript z předchozí kapitoly můžeme snadno umístit na webovou stránku a nechat si ho spustit ve webovém prohlížeči. Využijeme přitom dvě nové značky, tedy py-envpy-script. První z těchto značek obsahuje konfiguraci, zde konkrétně specifikaci, které knihovny budeme využívat. V našem konkrétním případě bude obsah této značky následující:

<py-env>
    - numpy
    - matplotlib
</py-env>

Do značky py-script vložíme celý skript, přičemž namísto volání plt.show() bude posledním příkazem ve skriptu pouze výraz plt (bez return). Právě tento příkaz po svém vyhodnocení povede k zobrazení grafu:

<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
<py-env>
    - numpy
    - matplotlib
</py-env>
    </head>
    <body>
        <py-script>
            import matplotlib
            import numpy as np
            import matplotlib.cm as cm
            import matplotlib.mlab as mlab
            import matplotlib.pyplot as plt
 
            delta = 0.1
 
            x = np.arange(-10.0, 10.0, delta)
            y = np.arange(-10.0, 10.0, delta)
 
            X, Y = np.meshgrid(x, y)
 
            R1 = np.sqrt(X * X + Y * Y)
            R2 = np.sqrt((X - 3) * (X - 3) + (Y - 3) * (Y - 3))
 
            Z = np.sin(R1) - np.cos(R2)
 
            plt.grid(True)
 
            plt.contour(X, Y, Z)
            plt
        </py-script>
    </body>
</html>

Načítání a inicializace stránky bude v tomto případě pomalejší:

Obrázek 4: Načítání a inicializace stránky.

Po několika sekundách by se ovšem měl graf zobrazit a měl by vypadat následovně:

Obrázek 5: Graf vykreslený do plochy stránky.

4. Zobrazení 3D grafu s průběhem funkce z=f(x,y)

Použití grafu s konturami sice může být v mnoha ohledech velmi užitečné (například při zjišťování lokálních minim a maxim i při potřebě nezkresleného pohledu na průběh funkce), v praxi se však spíše setkáme s odlišným typem grafů zobrazujících funkce typu z=f(x,y). Jedná se o trojrozměrné grafy, v nichž se zobrazuje plocha funkce. Nejjednodušším typem tohoto grafu je takzvaný drátový model, který je spíše známý pod svým anglickým názvem wireframe.

wireframe

Obrázek 6: Drátový model.

V tomto typu grafu je zobrazena série křivek či spíše lomených čar. Jedna série je vypočtena takovým způsobem, že x-ová souřadnice se postupně mění v nastaveném intervalu zatímco y-ová souřadnice je konstantní. Druhá série lomených čar se vykresluje kolmo na sérii první, tj. x-ová souřadnice je konstantní a postupně se mění hodnota y-ových souřadnic. Výsledkem je tedy plocha, která má při pohledu z osy z tvar pravidelné mřížky. Pro vykreslení tohoto typu grafu se používá funkce nazvaná plot_wireframe(), které se předá trojice polí odpovídajících x-ovým, y-ovým a z-ovým souřadnicím bodů ležících na ploše představujících obraz funkce:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
 
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
 
delta = 0.1
 
# průběh nezávislé proměnné x
x = np.arange(-10.0, 10.0, delta)
 
# průběh nezávislé proměnné y
y = np.arange(-10.0, 10.0, delta)
 
# vytvoření dvou polí se souřadnicemi [x,y] 
X, Y = np.meshgrid(x, y)
 
# vzdálenost od bodu [0,0]
R = np.sqrt(X*X+Y*Y)
 
# výpočet funkce, kterou použijeme při vykreslování grafu
Z = np.sin(R)/R
 
# zobrazení 3D grafu
ax.plot_wireframe(X, Y, Z, rstride=7, cstride=7)
 
# zobrazení grafu
plt.show()
meshgrid

Obrázek 7: Výsledný graf vykreslený předchozím skriptem, změna hustoty mřížky.

Drátový model je možné v případě potřeby nahradit vykreslením vyplněné plochy namísto pouhé mřížky. V tomto případě je nutné namísto funkce plot_wireframe() použít funkci pojmenovanou plot_surface(). První tři povinné parametry obou zmíněných funkcí jsou shodné, dokonce lze použít i stejně pojmenované parametry cstride a rstride, o jejichž významu jsme se taktéž zmiňovali v předchozích kapitolách. Kromě toho se však navíc většinou používá i další pojmenovaný parametr cmap, kterému se předá barvová paleta (či barvová mapa), která typicky definuje jeden gradientní přechod i větší množství gradientních přechodů mezi různými odstíny. Pro účely vytváření gradientních přechodů či pro použití již předem připravených barvových map se používá specializovaný modul nazvaný matplotlib.cm (color map). Seznam všech předdefinovaných barvových map naleznete na adrese https://gist.github.com/en­dolith/2719900#id7, ukázky (palety) pak na adrese http://matplotlib.org/exam­ples/color/colormaps_refe­rence.html. My využijeme barvovou mapu pojmenovanou „coolwarm“:

graf

Obrázek 8: Výsledný graf vykreslený předchozím skriptem.

Vzhledem k tomu, že se pro zobrazení trojrozměrného grafu na 2D obrazovce musí používat axonometrické promítání popř. promítání s perspektivou, nemusí být z výsledného obrázku s grafem na první pohled zřejmé, jak přesně vlastně průběh funkce vypadá. Knihovna Matplotlib nám však nabízí určité řešení tohoto problému – na plochy (které jsou kolmé na osy souřadného systému) se promítnou kontury průběhu funkce. Podívejme se nejdříve na to, jak vypadá výsledek:

graf

Obrázek 9: Výsledný graf vykreslený předchozím skriptem.

Samotná plocha představující funkci se vykreslí příkazem (přesněji řečeno funkcí) matplotlib.pyplot.plot_surface(), podobně jako v předchozím příkladu. Dále se metodou ax.contour() mohou vykreslit kontury grafu na jednotlivé plochy, ve skutečnosti je však ještě nutné korektně nastavit přesné umístění těchto kontur do grafu. K tomu slouží explicitní nastavení rozsahů na jednotlivých osách (set_xlim(), set_ylim(), set_zlim()) a vlastní posun reprezentovaný pojmenovaným parametrem offset předaným do metody ax.contour(). Podívejme se na odladěný příklad:

from mpl_toolkits.mplot3d import axes3d
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
 
fig = plt.figure()
ax = fig.gca(projection='3d')
 
delta = 0.1
 
# průběh nezávislé proměnné x
x = np.arange(-10.0, 10.0, delta)
 
# průběh nezávislé proměnné y
y = np.arange(-10.0, 10.0, delta)
 
# vytvoření dvou polí se souřadnicemi [x,y]
X, Y = np.meshgrid(x, y)
 
# vzdálenost od bodu [0,0]
R = np.sqrt(X*X+Y*Y)
 
# výpočet funkce, kterou použijeme při vykreslování grafu
Z = np.sin(R)/R
 
# zobrazení 3D grafu formou plochy
surface = ax.plot_surface(X, Y, Z, rstride=2, cstride=2, cmap=cm.coolwarm,
                          linewidth=0, antialiased=False)
 
# kontutra: průmět na rovinu x-y
cset = ax.contour(X, Y, Z, zdir='z', offset=-5, cmap=cm.coolwarm)
 
# kontutra: průmět na rovinu y-z
cset = ax.contour(X, Y, Z, zdir='x', offset=-15, cmap=cm.coolwarm)
 
# kontutra: průmět na rovinu x-z
cset = ax.contour(X, Y, Z, zdir='y', offset=15, cmap=cm.coolwarm)
 
# rozměry grafu ve směru osy x
ax.set_xlabel('X')
ax.set_xlim(-15, 15)
 
# rozměry grafu ve směru osy y
ax.set_ylabel('Y')
ax.set_ylim(-15, 15)
 
# rozměry grafu ve směru osy z
ax.set_zlabel('Z')
ax.set_zlim(-5, 5)
 
# zobrazení grafu
plt.show()

5. 3D graf vykreslený na ploše webové stránky

Výše uvedený skript je již velmi snadné přenést do webové stránky. Buď můžeme skript vložit přímo do HTML kódu, jak je to ostatně ukázáno níže, nebo je možné skript načíst přes pyscript src="plot3.py, což však již vyžaduje použití nějakého HTTP serveru, a to i při vývoji (popř. je nutné změnit konfiguraci webového prohlížeče, aby neblokoval načítání lokálních souborů):

<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
<py-env>
    - numpy
    - matplotlib
</py-env>
    </head>
    <body>
        <py-script>
            from matplotlib import cm
            import matplotlib.pyplot as plt
            import numpy as np
 
            fig = plt.figure()
            ax = fig.gca(projection="3d")
 
            delta = 0.1
 
            x = np.arange(-10.0, 10.0, delta)
            y = np.arange(-10.0, 10.0, delta)
 
            X, Y = np.meshgrid(x, y)
 
            R = np.sqrt(X * X + Y * Y)
            Z = np.sin(R) / R
 
            surface = ax.plot_surface(
                X, Y, Z, rstride=2, cstride=2, cmap=cm.coolwarm, linewidth=0, antialiased=False
            )
 
            cset = ax.contour(X, Y, Z, zdir="z", offset=-5, cmap=cm.coolwarm)
            cset = ax.contour(X, Y, Z, zdir="x", offset=-15, cmap=cm.coolwarm)
            cset = ax.contour(X, Y, Z, zdir="y", offset=15, cmap=cm.coolwarm)
 
            ax.set_xlabel("X")
            ax.set_xlim(-15, 15)
 
            ax.set_ylabel("Y")
            ax.set_ylim(-15, 15)
 
            ax.set_zlabel("Z")
            ax.set_zlim(-5, 5)
 
            plt
        </py-script>
    </body>
</html>

Obrázek 10: 3D graf zobrazený přímo na ploše webové stránky.

6. Změna velikosti obrázku s grafem

Nyní si ukažme, jakým způsobem je možné změnit velikost grafu, resp. rozlišení rastrového obrázku, do kterého se graf vykreslí. Jak jste si mohli povšimnout, je implicitní velikost obrázků s grafem na dnešní poměry relativně malá. Graf je však možné zvětšit, konkrétně vypnutím takzvaných bounding boxů a především nastavením velikosti v palcích:

plt.figure(1, figsize=(8,6), dpi=100)
Poznámka: hodnota DPI je specifikována z toho důvodu, že přepočet palců na pixely je snadnější, než při výchozí hodnotě DPI=75 bodů na palec.

Upravená HTML stránka, která by měla při svém načtení do webového prohlížeče zobrazit zvětšený graf kontury funkce, vypadá následovně:

<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
<py-env>
    - numpy
    - matplotlib
</py-env>
    </head>
    <body>
        <py-script>
            import matplotlib
            import numpy as np
            import matplotlib.cm as cm
            import matplotlib.mlab as mlab
            import matplotlib.pyplot as plt
 
            plt.figure(1, figsize=(8,8), dpi=100)
 
            delta = 0.1
 
            x = np.arange(-10.0, 10.0, delta)
            y = np.arange(-10.0, 10.0, delta)
 
            X, Y = np.meshgrid(x, y)
 
            R1 = np.sqrt(X * X + Y * Y)
            R2 = np.sqrt((X - 3) * (X - 3) + (Y - 3) * (Y - 3))
 
            Z = np.sin(R1) - np.cos(R2)
 
            plt.grid(True)
 
            plt.contour(X, Y, Z)
            plt
        </py-script>
    </body>
</html>

Povšimněte si, že nyní se již celý graf ani nevejde na plochu mého monitoru:

Obrázek 11: Graf s konturami funkce zobrazený přímo na ploše webové stránky.

7. Pythonovská interaktivní smyčka REPL přímo na ploše webové stránky

S principem a použitím interaktivní smyčky REPL jsme se již na stránkách Rootu setkali, a to dokonce mnohokrát. Kromě článků, které se věnovaly klasickým Unixovým shellům typu BASH, tcsh či zsh (a rozhraní shellů není nic jiného, než interaktivní REPL), jsme smyčku REPL použili například při popisu programovacího jazyka Julia či jazyka Clojure. Historií vzniku REPL jsme se zabývali i zde.

PyScript taktéž umožňuje přímo na plochu webové stránky vložit REPL resp. přesněji řečeno vstupní pole, do kterého je možné zapisovat příkazy, které se ihned poté vykonají. Dokonce je možné na stránku vložit větší množství REPLů. Jedná se tak vlastně o mezikrok mezi klasickými REPLy a diáři (notebooky), mezi které patří i známý Jupyter Notebook.

Poznámka: REPL implementovaný v PyScriptu podporuje víceřádkové příkazy resp. bloky kódu, takže lze snadno tvořit programové smyčky, zapisovat větší matice atd.

8. REPL bez předvyplněného obsahu (základní podoba značky py-repl)

Nejjednodušší forma vstupního prvku pro interaktivní smyčku REPL může vypadat následovně. Povšimněte si, že jsme do stránky vložili pouze prázdnou značku py-repl:

<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
    </head>
    <h1>Python REPL</h1>
    <py-repl></py-repl>
</html>

Výsledkem bude stránka, která by po své inicializaci měla vypadat následovně:

Obrázek 12: Webová stránka se zobrazeným vstupem do smyčky REPL.

Přes REPL si pochopitelně můžeme nechat vyhodnotit nějaký jednoduchý výraz:

Obrázek 13: Vyhodnocení jednoduchého výrazu ve smyčce REPL.

Poznámka: povšimněte si, že se nemusí psát příkaz print, ale i tak je výsledek zobrazen.

Zápis programového bloku na více řádcích je taktéž možný. Zde však již musíme explicitně zapsat příkaz print, protože by se zobrazil jen výsledek posledního výrazu (což je None):

Obrázek 14: Programová smyčka zapsaná na dvou řádcích v REPLu.

Ukázka, že je skutečně zobrazen výsledek posledního výrazu:

Obrázek 15: Zobrazení výsledku posledního výrazu.

9. Vstupní prvek smyčky REPL s předvyplněným obsahem

Vzhledem k tomu, že py-repl je párovou značkou, nic nám nezabraňuje v tom, abychom do ní přímo zapsali nějaký obsah – tedy běžný Pythonovský skript nebo jeho část. To se hodí například pro výukové účely atd.:

<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
    </head>
    <h1>Python REPL</h1>
 
    <py-repl>
def run():
    for i in range(1,11):
        print(i)
 
run()
    </py-repl>
</html>

Výsledná webová stránka bude nyní vypadat následovně:

Obrázek 16: Smyčka REPL s předvyplněným obsahem.

Po stisku zelené šipky nebo po použití klávesové zkratky Shift+Enter se kód zapsaný v REPLu spustí a vyhodnotí:

Obrázek 17: Spuštění a vyhodnocení kódu zapsaného do REPLu.

10. Interaktivní vykreslování grafů na webové stránce

Nic nám pochopitelně nebrání ve zkombinování možností poskytovaných značkami py-env a py-repl. V dalším demonstračním příkladu je ukázáno, jakým způsobem lze předvyplnit REPL kódem, který po svém spuštění vykreslí do plochy webové stránky graf:

<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
<py-env>
    - numpy
    - matplotlib
</py-env>
    </head>
    <h1>Python REPL</h1>
 
    <py-repl>
            import numpy as np
            import matplotlib.pyplot as plt
 
            x = np.linspace(0, 2 * np.pi, 100)
 
            y = np.sin(x)
 
            plt.plot(x, y)
 
            plt.xlabel("x")
            plt.ylabel("sin(x)")
 
            plt
    </py-repl>
</html>

Výsledek bude vypadat následovně:

Obrázek 18: Předvyplněná smyčka REPL-

Obrázek 19: Graf vykreslený po spuštění kódu ve smyčce REPL-

11. Interaktivní změna parametrů zobrazovaných funkcí

V případě, že budeme chtít uživatelům umožnit pouze změnit parametry zobrazované funkce (resp. dvou funkcí a jejich součtu), můžeme celý kód pro vykreslení „schovat“ do značky py-script a z py-repl pouze volat definovanou funkci plot:

<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
<py-env>
    - numpy
    - matplotlib
</py-env>
    </head>
    <h1>Python REPL</h1>
 
    <py-script>
        import numpy as np
        import matplotlib.pyplot as plt
 
        def plot(amplitude, frequency, offset):
            print("plot begin")
            x = np.linspace(0, 2 * np.pi, 100)
            y1 = np.sin(x)
            y2 = amplitude * np.sin(x*frequency) + offset
 
            plt.plot(x, y1, x, y2, x, y1+y2)
 
            print("plot end")
            return plt
    </py-script>
 
    <py-repl>
        plot(0.6, 2, 0)
    </py-repl>
</html>

Obrázek 20: Předvyplněná smyčka REPL-

Obrázek 21: Graf vykreslený po spuštění kódu ve smyčce REPL-

Poznámka: v případě, že vám nevyhovuje fakt, že se do grafu funkce přidávají (po každém vyhodnocení REPLu se přidají nové průběhy), přidejte do funkce plot volání plt.clf(), což zajistí smazání grafu před jeho dalším vykreslením:
<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
<py-env>
    - numpy
    - matplotlib
</py-env>
    </head>
    <h1>Python REPL</h1>
 
    <py-script>
        import numpy as np
        import matplotlib.pyplot as plt
 
        def plot(amplitude, frequency, offset):
            print("plot begin")
            x = np.linspace(0, 2 * np.pi, 100)
            y1 = np.sin(x)
            y2 = amplitude * np.sin(x*frequency) + offset
 
            plt.clf()
            plt.plot(x, y1, x, y2, x, y1+y2)
 
            print("plot end")
            return plt
    </py-script>
 
    <py-repl>
        plot(0.6, 2, 0)
    </py-repl>
</html>

12. Reakce na události: zavolání funkce naprogramované v Pythonu po stisku tlačítka

I když značka py-repl do webových stránek přináší interaktivitu, je v mnoha případech zapotřebí zajistit, aby se nějaká Pythonovská funkce zavolala ve chvíli, kdy uživatel například stiskne tlačítko zobrazené na webové stránce popř. když provede nějakou další podobnou operaci. Jinými slovy – potřebujeme umět reagovat na události, které mohou na webové stránce v průběhu jejího zobrazení nastat.

Vložme tedy do webové stránky tlačítko, přesněji řečeno značku buttob. Povšimněte si, že této značce není možné přímo do atributu on-click předat Pythonovskou funkci (ta by nebyla webovým prohlížečem nalezena, neboť by hledal ve jmenném prostoru JavaScriptu):

<button class="button" type="button" class="py-button" id="calculate-button">Calculate!</button>

V reakci na stisk výše uvedeného tlačítka budeme chtít spustit tuto funkci, s níž jsme se ostatně již seznámili minule:

def calculate(event):
    print("begin")
 
    # original code
    # http://www.rosettacode.org/wiki/Sieve_of_Eratosthenes#Using_array_lookup
    def primes2(limit):
        is_prime = [False] * 2 + [True] * (limit - 1)
        for n in range(int(limit ** 0.5 + 1.5)):  # stop at ``sqrt(limit)``
            if is_prime[n]:
                for i in range(n * n, limit + 1, n):
                    is_prime[i] = False
        return [i for i, prime in enumerate(is_prime) if prime]
 
 
    primes = primes2(100)
    asStrings = map(str, primes)
    pyscript.write('result', ", ".join(asStrings))

13. Propojení události s Pythonovským kódem přes proxy

Aby se po stisku tlačítka zobrazeného na webové stránce spustila funkce zapsaná v Pythonu, je nutné tyto dvě entity propojit přes takzvanou proxy, která interně vše zařídí s využitím JavaScriptu (což je však z pohledu programátora skryto v hlubinách PyScriptu). Náš úkol je jednoduchý – propojit událost „click“ prvku s identifikátorem „calculate-button“ s Pythonovskou funkcí nazvanou calculate. Příslušnou proxy lze vytvořit zavoláním create_proxy a vzhledem k tomu, že z pohledu webového prohlížeče se jedná o běžnou JavaScriptovou funkci, můžeme ji zaregistrovat jako handler příslušné události:

def setup():
    click_proxy = create_proxy(calculate)
 
    e = document.getElementById("calculate-button")
    e.addEventListener("click", click_proxy)

Výsledná webová stránka, na které se tlačítko použité přes proxy využije, vypadá následovně:

<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
    </head>
    <body>
        <div id="result" style="font-size:150%;color:#800000"></div>
 
        <py-script>
        def calculate(event):
            print("begin")
 
            # original code
            # http://www.rosettacode.org/wiki/Sieve_of_Eratosthenes#Using_array_lookup
            def primes2(limit):
                is_prime = [False] * 2 + [True] * (limit - 1)
                for n in range(int(limit ** 0.5 + 1.5)):  # stop at ``sqrt(limit)``
                    if is_prime[n]:
                        for i in range(n * n, limit + 1, n):
                            is_prime[i] = False
                return [i for i, prime in enumerate(is_prime) if prime]
 
 
            primes = primes2(100)
            asStrings = map(str, primes)
            pyscript.write('result', ", ".join(asStrings))
 
        from js import document
        from pyodide import create_proxy
 
        def setup():
            click_proxy = create_proxy(calculate)
 
            e = document.getElementById("calculate-button")
            e.addEventListener("click", click_proxy)
 
        setup()
        </py-script>
 
        <button class="button" type="button" class="py-button" id="calculate-button">Calculate!</button>
</html>

Výsledné chování webové stránky si můžeme velmi snadno ověřit:

Obrázek 22: Webová stránka před stiskem tlačítka.

Obrázek 23: Webová stránka po stisku tlačítka.

14. Přečtení hodnoty uložené v interaktivním prvku webové stránky

Předchozí demonstrační příklad se můžeme pokusit dále upravit, například takovým způsobem, že uživateli umožníme specifikaci horního limitu při výpočtu prvočísel. Konkrétně tedy nebudeme hledat prvočísla ležící v rozsahu 2 až 100, ale v rozsahu 2 až X, kde hodnota X bude zapsána uživatelem do tohoto vstupního prvku:

Limit: <input type="text" id="limit" value="100" size="5" />

Hodnotu zapsanou do tohoto prvku získáme v Pythonovském kódu snadno:

value = Element('limit').value

V tom nejjednodušším případě nebudeme kontrolovat typ zapsané hodnoty ani to, jestli náhodou není zapsána záporná hodnota atd.:

limit = int(Element('limit').value)
Poznámka: v případě, že uživatel do vstupního pole zapíše například „xyzzy“, dojde k běhové chybě, která je vypsána do plochy webové stránky:

Obrázek 24: Běhová chyba, která vznikne při pokusu o převod řetězce „xyzzy“ na celé číslo.

Opět se podívejme na to, jak se oba dva výše popsané řádky vloží do zdrojového kódu interaktivní webové stránky:

<html>
    <head>
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
    </head>
    <body>
        <py-script>
        def calculate(event):
            print("begin")
 
            # original code
            # http://www.rosettacode.org/wiki/Sieve_of_Eratosthenes#Using_array_lookup
            def primes2(limit):
                is_prime = [False] * 2 + [True] * (limit - 1)
                for n in range(int(limit ** 0.5 + 1.5)):  # stop at ``sqrt(limit)``
                    if is_prime[n]:
                        for i in range(n * n, limit + 1, n):
                            is_prime[i] = False
                return [i for i, prime in enumerate(is_prime) if prime]
 
            limit = int(Element('limit').value)
 
            primes = primes2(limit)
            asStrings = map(str, primes)
            Element('result').write(", ".join(asStrings))
 
        from js import document
        from pyodide import create_proxy
 
        def setup():
                click_proxy = create_proxy(calculate)
 
                e = document.getElementById("calculate-button")
                e.addEventListener("click", click_proxy)
 
        setup()
        </py-script>
 
        Limit: <input type="text" id="limit" value="100" size="5" />
        <br />
        <button class="button" type="button" class="py-button" id="calculate-button">Calculate!</button>
        <br />
        <div id="result" style="font-size:150%;color:#800000"><u>...result...</u></div>
 
</html>

Chování webové stránky si snadno ověříme:

Obrázek 25: Webová stránka před stiskem tlačítka.

Obrázek 26: Webová stránka po vyplnění limitu a stisku tlačítka.

15. Zobrazení grafu po stisku tlačítka na webové stránce

V rámci závěrečných kapitol si ukážeme, jakým způsobem je možné s využitím PyScriptu vytvořit webovou stránku, která bude obsahovat několik vstupních prvků určených pro specifikaci parametrů nějaké funkce. Stránka navíc bude umožňovat zobrazení průběhu této funkce. Celý úkol si tedy můžeme rozdělit na několik kroků, z nichž všechny jsme si vlastně již vysvětlili v předchozím textu:

  1. Neinteraktivní zobrazení grafu ihned po inicializaci webové stránky.
  2. Zobrazení grafu po stisku k tomu určeného tlačítka.
  3. Vložení dalších interaktivních prvků na webovou stránku.
  4. Přečtení a interpretace hodnot zapsaných do těchto interaktivních prvků před zobrazením grafu.
Poznámka: později je pochopitelně možné vlastnosti dále rozšiřovat, například přidat prvek pro výběr funkce, která se má zobrazit, přidat prvek pro zápis této funkce (s případnými kontrolami) atd.

Podívejme se nicméně na to, jak je možné realizovat druhý bod z uvedeného seznamu (první bod jsme již realizovali v úvodním článku). Vytvořená webová stránka obsahuje kód určený pro zobrazení grafu a tento kód je zavolán až po stisku tlačítka Plot!:

<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
    </head>
<py-env>
    - numpy
    - matplotlib
</py-env>
    <body>
        <div id="plot"></div>
 
        <py-script>
            import numpy as np
            import matplotlib.pyplot as plt
            from js import document
            from pyodide import create_proxy
 
            def plot(event):
                amplitude = 1.0
                frequency = 2
                offset = 0
 
                print("plot begin")
 
                x = np.linspace(0, 2 * np.pi, 100)
                y1 = np.sin(x)
                y2 = amplitude * np.sin(x*frequency) + offset
 
                plt.clf()
                plt.plot(x, y1, x, y2, x, y1+y2)
 
                print("plot end")
                Element('plot').write(plt)
                return plt
 
            def setup():
                    click_proxy = create_proxy(plot)
 
                    e = document.getElementById("plot-button")
                    e.addEventListener("click", click_proxy)
 
            setup()
        </py-script>
 
        <button class="button" type="button" class="py-button" id="plot-button">Plot!</button>
</html>

Výsledek by měl vypadat následovně:

Obrázek 27: Webová stránka po své inicializaci obsahuje pouze jediné tlačítko.

Obrázek 28: Graf zobrazený po stisku tlačítka.

16. Interaktivní prvky pro zadání amplitudy, frekvence a posunutí zobrazované funkce

Na plochu HTML stránky nyní přidáme další ovládací prvky (formulář) s možností zadání amplitudy, frekvence a posunutí zobrazované funkce:

<div class="input-form">
    <div>Amplitude</div>
    <input type="text" id="amplitude" value="1" size="5" />
    <div>Frequency</div>
    <input type="text" id="frequency" value="2" size="5" />
    <div>Offset</div>
    <input type="text" id="offset" value="0" size="5" />
    <div></div>
    <button type="button" id="plot-button" class="button">Plot!</button>
</div>

Stránka by po této úpravě měla vypadat následovně:

Obrázek 29: Webová stránka po své inicializaci obsahuje pouze ovládací prvky.

Po stisku tlačítka Plot! se graf vykreslí, přičemž se získají a použijí hodnoty z formuláře:

amplitude = float(Element('amplitude').value)
frequency = float(Element('frequency').value)
offset = float(Element('offset').value)
Poznámka: povšimněte si, že prozatím neprovádíme žádnou kontrolu zadaných hodnot.

Obrázek 30: Graf zobrazený po vyplnění hodnot a stisku tlačítka.

Celý skript by měl nyní vypadat následovně:

<html>
    <head>
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
 
        <style type="text/css">
        .input-form {
            display: grid;
            grid-template-columns: 16ex 10ex;
            grid-column: 2;
            background-color: #c0c0c0;
            padding: 5px;
        }
        .button {
            background-color: #f08080;
        }
        </style>
    </head>
<py-env>
    - numpy
    - matplotlib
</py-env>
    <body>
        <py-script>
            import numpy as np
            import matplotlib.pyplot as plt
            from js import document
            from pyodide import create_proxy
 
            def plot(event):
                amplitude = float(Element('amplitude').value)
                frequency = float(Element('frequency').value)
                offset = float(Element('offset').value)
 
                print("plot begin")
 
                x = np.linspace(0, 2 * np.pi, 100)
                y1 = np.sin(x)
                y2 = amplitude * np.sin(x*frequency) + offset
 
                plt.clf()
                plt.plot(x, y1, x, y2, x, y1+y2)
 
                print("plot end")
                Element('plot').write(plt)
                return plt
 
            def setup():
                    click_proxy = create_proxy(plot)
 
                    e = document.getElementById("plot-button")
                    e.addEventListener("click", click_proxy)
 
            setup()
        </py-script>
 
        <div class="input-form">
            <div>Amplitude</div>
            <input type="text" id="amplitude" value="1" size="5" />
            <div>Frequency</div>
            <input type="text" id="frequency" value="2" size="5" />
            <div>Offset</div>
            <input type="text" id="offset" value="0" size="5" />
            <div></div>
            <button type="button" id="plot-button" class="button">Plot!</button>
        </div>
 
        <div id="plot"></div>
 
</html>

17. Úprava předchozího demonstračního příkladu – reakce na nesprávné vstupy

A konečně do skriptu přidáme kontroly, zda uživatel do formuláře skutečně zapsal numerické hodnoty a nikoli například řetězec, ponechal vstupní pole prázdné atd. Tyto kontroly je nutné provést, protože samotné HTML sice obsahuje možnost specifikace typu hodnot, ale to platí pouze pro odesílání formulářů a v našem případě je tedy nepoužitelné. Úprava, tedy přidání kontrol, je snadná:

def retrieve_float_from_element(name, element):
    value = Element(element).value
 
    try:
        return float(value)
    except Exception as e:
        alert(f"Incorrect {name} value: {value}")
        raise
 
def plot(event):
    try:
        amplitude = retrieve_float_from_element("amplitude", "amplitude")
        frequency = retrieve_float_from_element("frequency", "frequency")
        offset = retrieve_float_from_element("offset", "offset")
        ...
        ...
        ...

Příklad reakce na nesprávný vstup:

Obrázek 31: Reakce na nesprávný vstup.

Upravený kód webové stránky bude vypadat následovně:

<html>
    <head>
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
 
        <style type="text/css">
        .input-form {
            display: grid;
            grid-template-columns: 16ex 10ex;
            grid-column: 2;
            background-color: #c0c0c0;
            padding: 5px;
        }
        .button {
            background-color: #f08080;
        }
        </style>
    </head>
<py-env>
    - numpy
    - matplotlib
</py-env>
    <body>
        <py-script>
            import numpy as np
            import matplotlib.pyplot as plt
            from js import document
            from js import alert
            from pyodide import create_proxy
 
            def retrieve_float_from_element(name, element):
                value = Element(element).value
 
                try:
                    return float(value)
                except Exception as e:
                    alert(f"Incorrect {name} value: {value}")
                    raise
 
            def plot(event):
                try:
                    amplitude = retrieve_float_from_element("amplitude", "amplitude")
                    frequency = retrieve_float_from_element("frequency", "frequency")
                    offset = retrieve_float_from_element("offset", "offset")
 
                    print("plot begin")
 
                    x = np.linspace(0, 2 * np.pi, 100)
                    y1 = np.sin(x)
                    y2 = amplitude * np.sin(x*frequency) + offset
 
                    plt.clf()
                    plt.plot(x, y1, x, y2, x, y1+y2)
 
                    print("plot end")
                    Element('plot').write(plt)
                except Exception as e:
                    pass
 
            def setup():
                    click_proxy = create_proxy(plot)
 
                    e = document.getElementById("plot-button")
                    e.addEventListener("click", click_proxy)
 
            setup()
        </py-script>
 
        <div class="input-form">
            <div>Amplitude</div>
            <input type="text" id="amplitude" value="1" size="5" />
            <div>Frequency</div>
            <input type="text" id="frequency" value="2" size="5" />
            <div>Offset</div>
            <input type="text" id="offset" value="0" size="5" />
            <div></div>
            <button type="button" id="plot-button" class="button">Plot!</button>
        </div>
 
        <div id="plot"></div>
 
</html>

Obrázek 32: Graf zobrazený po vyplnění hodnot a stisku tlačítka.

root_podpora

18. Závěrečné zhodnocení

PyScript je velmi zajímavý a potenciálně i užitečný projekt, který umožňuje přímo na webové stránce používat programovací jazyk Python a současně i jeho nejpoužívanější knihovny (zde konkrétně často používanou trojici NumPy+Pandas+Matplotlib). Nevýhodou je zejména příliš dlouhý interval nutný pro inicializaci stránky, především při prvním načítání jakékoli stránky s PyScriptem, neboť se do cache prohlížeče musí nahrát i všechny potřebné knihovny (při dalším načítání jsou již načítány z cache). Výhodou (a někdy i nevýhodou) řešení postaveného na PyScriptu je přenesení zátěže na klienta, zatímco samotný server pouze přenáší požadované soubory popř. zpřístupňuje databáze. Z těchto důvodů je PyScript v jeho současné podobě vhodný spíše pro intranetové aplikace – analýzy dat, tvorbu reportů, různé dashboardy atd. Na webové aplikace typu obchod či dokonce pro realizaci serveru typu Root se PyScript prozatím příliš nehodí.

19. Repositář s demonstračními příklady

Zdrojové kódy všech prozatím popsaných demonstračních příkladů určených pro spuštění ve webovém prohlížeči s využitím nástroje PyScript byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/most-popular-python-libs. V případě, že nebudete chtít klonovat celý repositář (ten je ovšem stále velmi malý, dnes má velikost zhruba několik desítek kilobajtů), můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:

# Demonstrační příklad Stručný popis příkladu Cesta
1 hello1.html program „Hello, World“ vytvořený pro PyScript https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/hello1.html
2 hello2.html spuštění externího skriptu načteného přes src https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/hello2.html
3 hello3.html kratší zápis značky py-script https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/hello3.html
4 hello.py skript načtený předchozími dvěma příklady https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/hello.py
       
5 loop1.html smyčka v Pythonu zapsaná přímo do HTML stránky https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/loop1.html
6 loop2.html spuštění externího skriptu načteného přes src https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/loop2.html
7 loop3.html kratší zápis značky py-script https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/loop3.html
8 loop.py skript načtený předchozími dvěma příklady https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/loop.py
       
9 primes1.html výpočet řady prvočísel s jejich zobrazením https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/primes1.html
10 primes2.html výpočet řady prvočísel, zápis výsledku do vybraného elementu HTML stránky https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/primes2.html
11 primes3.html výpočet řady prvočísel, vylepšený zápis výsledku do vybraného elementu HTML stránky https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/primes3.html
12 primes4.html specifikace cesty k lokálnímu modulu https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/primes4.html
13 primes.py skript načtený předchozím příkladem https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/primes.py
       
14 numpy1.html využití knihovny NumPy, zobrazení maticového součinu https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/numpy1.html
15 numpy2.html využití knihovny NumPy, pretty printing matice https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/numpy2.html
16 numpy3.html využití knihovny NumPy, zobrazení většího množství matic https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/numpy3.html
       
17 matplotlib1.html liniový graf vykreslený knihovnou Matplotlib https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/mat­plotlib1.html
18 matplotlib2.html konturový graf vykreslený knihovnou Matplotlib https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/mat­plotlib2.html
19 matplotlib3.html trojrozměrný graf vykreslený knihovnou Matplotlib https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/mat­plotlib3.html
20 matplotlib4.html změna rozměrů grafu na stránce https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/mat­plotlib4.html
       
21 repl1.html zobrazení REPLu na webové stránce https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/repl1.html
22 repl2.html zobrazení REPLu na webové stránce, předvyplnění zdrojového kódu https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/repl2.html
23 repl3.html zobrazení REPLu na webové stránce, využití kombinace NumPy + Matplotlib https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/repl3.html
24 repl4.html zobrazení REPLu na webové stránce, využití kombinace NumPy + Matplotlib https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/repl4.html
25 repl5.html zobrazení REPLu na webové stránce, využití kombinace NumPy + Matplotlib, vymazání grafu před jeho opětovným vykreslením https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/repl5.html
       
26 onclick1.html reakce na stisk tlačítka, zavolání funkce v Pythonu po stisku tlačítka https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/on­click2.html
27 onclick2.html reakce na stisk tlačítka, přečtení hodnoty zapsané do vstupního pole (komunikace s webovou stránkou) https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/on­click2.html
28 onclick3.html reakce na stisk tlačítka, vykreslení grafu (opět komunikace s webovou stránkou) https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/on­click3.html
29 onclick4.html vykreslení grafu s nastavením jeho vlastností (další příklad komunikace s webovou stránkou) https://github.com/tisnik/most-popular-python-libs/blob/master/pyscript/on­click4.html

20. Odkazy na Internetu

  1. PyScript
    https://pyscript.net/
  2. PyScript na GitHubu
    https://github.com/pyscript/pyscript
  3. Getting started with PyScript
    https://github.com/pyscrip­t/pyscript/blob/main/docs/tu­torials/getting-started.md
  4. PyScript examples
    https://github.com/pyscrip­t/pyscript/tree/main/exam­ples
  5. What is PyScript
    https://docs.pyscript.net/la­test/concepts/what-is-pyscript.html
  6. Pyodide
    https://pyodide.org/en/stable/
  7. PyScript: JavaScript and Python Interoperability
    https://www.jhanley.com/blog/pyscript-javascript-and-python-interoperability/
  8. Pyscript: JavaScript Event Callbacks
    https://www.jhanley.com/blog/pyscript-javascript-callbacks/
  9. Compiling to WebAssembly: It’s Happening!
    https://hacks.mozilla.org/2015/12/com­piling-to-webassembly-its-happening/
  10. WebAssembly
    https://webassembly.org/
  11. Blogy o WASM a Emscripten
    https://www.jamesfmackenzi­e.com/sitemap/#emscripten
  12. wat2wasm demo
    https://webassembly.github­.io/wabt/demo/wat2wasm/
  13. WABT: The WebAssembly Binary Toolkit
    https://github.com/WebAssembly/wabt
  14. Programming using Web Assembly
    https://medium.com/@alexc73/pro­gramming-using-web-assembly-c4c73a4e09a9
  15. Experiments with image manipulation in WASM using Go
    https://agniva.me/wasm/2018/06/18/shim­mer-wasm.html
  16. Fable
    https://fable.io/
  17. Využití WebAssembly z programovacího jazyka Go
    https://www.root.cz/clanky/vyuziti-webassembly-z-programovaciho-jazyka-go/
  18. WebAssembly prošlo standardizací ve W3C, byla vydána verze 1.0
    https://www.root.cz/zpravic­ky/webassembly-proslo-standardizaci-ve-w3c-byla-vydana-verze-1–0/
  19. WebAssembly na Wiki Golangu
    https://github.com/golang/go/wi­ki/WebAssembly
  20. The future of WebAssembly – A look at upcoming features and proposals
    https://blog.scottlogic.com/2018/07/20/wasm-future.html
  21. Writing WebAssembly By Hand
    https://blog.scottlogic.com/2018/04/26/we­bassembly-by-hand.html
  22. WebAssembly Specification
    https://webassembly.github­.io/spec/core/index.html
  23. Index of Instructions
    https://webassembly.github­.io/spec/core/appendix/in­dex-instructions.html
  24. The WebAssembly Binary Toolkit
    https://github.com/WebAssembly/wabt
  25. 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
  26. Roadmap (pro WebAssemly)
    https://webassembly.org/roadmap/
  27. S-expression
    https://en.wikipedia.org/wiki/S-expression
  28. Understanding WebAssembly text format
    https://developer.mozilla.org/en-US/docs/WebAssembly/Under­standing_the_text_format
  29. Learning Golang through WebAssembly – Part 1, Introduction and setup
    https://www.aaron-powell.com/posts/2019–02–04-golang-wasm-1-introduction/
  30. 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/
  31. 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/
  32. Golang webassembly (wasm) testing with examples
    https://jelinden.fi/blog/golang-webassembly-wasm-testing-with-examples/qB7Tb2KmR
  33. Use Cases (of WebAssembly)
    https://webassembly.org/docs/use-cases/
  34. JupyterLite na PyPi
    https://pypi.org/project/jupyterlite/
  35. JupyterLite na GitHubu
    https://github.com/jupyter­lite/jupyterlite
  36. Dokumentace k projektu JupyterLite
    https://github.com/jupyter­lite/jupyterlite
  37. A quick guide about Python implementations
    https://blog.rmotr.com/a-quick-guide-about-python-implementations-aa224109f321
  38. How Brython works
    https://github.com/brython-dev/brython/wiki/How%20Brython%20works
  39. Brython – A Python 3 implementation for client-side web programming
    http://www.brython.info/
  40. Brython videos and talks
    https://github.com/brython-dev/brython/wiki/Brython-videos-and-talks
  41. What is Brython?
    https://medium.com/frontendweb/what-is-brython-6edb424b07f6
  42. Python in browser (tabulka s porovnáními)
    http://stromberg.dnsalias­.org/~strombrg/pybrowser/pyt­hon-browser.html
  43. JavaScript is Assembly Language for the Web: Sematic Markup is Dead! Clean vs. Machine-coded HTML
    http://www.hanselman.com/blog/Ja­vaScriptIsAssemblyLanguage­ForTheWebSematicMarkupIsDe­adCleanVsMachinecodedHTML­.aspx
  44. pyscript VS brython
    https://www.libhunt.com/compare-pyscript-vs-brython
  45. PyScript – Run Python in the Browser! THE END of JavaScript???
    https://www.youtube.com/wat­ch?v=du8vQC44PC4
  46. PyScript is Python in Your Browser
    https://www.youtube.com/wat­ch?v=MJvCeKwr4z4
  47. JupyterLite na PyPi
    https://pypi.org/project/jupyterlite/
  48. JupyterLite na GitHubu
    https://github.com/jupyter­lite/jupyterlite
  49. Dokumentace k projektu JupyterLite
    https://github.com/jupyter­lite/jupyterlite
  50. Matplotlib Home Page
    http://matplotlib.org/
  51. Matplotlib (Wikipedia)
    https://en.wikipedia.org/wi­ki/Matplotlib
  52. Popis barvových map modulu matplotlib.cm
    https://gist.github.com/en­dolith/2719900#id7
  53. Ukázky (palety) barvových map modulu matplotlib.cm
    http://matplotlib.org/exam­ples/color/colormaps_refe­rence.html
  54. Galerie grafů vytvořených v Matplotlibu
    https://matplotlib.org/3.2.1/gallery/
  55. Replacing Javascript with Python
    https://stackoverflow.com/qu­estions/69510962/replacing-javascript-with-python
  56. Can Python Replace Javascript in the Future?
    https://dev.to/katholder/can-python-replace-javascript-in-the-future-4bbn
  57. asm.js
    http://asmjs.org/
  58. asm.js: Working Draft
    http://asmjs.org/spec/latest/
  59. Manual asm.js Demonstration
    https://www.youtube.com/wat­ch?v=qkiqMuf5M84
  60. asm.js – frequently asked questions
    http://asmjs.org/faq.html
  61. When asm.js is faster than normal JS code, why should I write new code in JS?
    https://stackoverflow.com/qu­estions/16527195/when-asm-js-is-faster-than-normal-js-code-why-should-i-write-new-code-in-js
  62. Faster Canvas Pixel Manipulation with Typed Arrays
    https://hacks.mozilla.org/2011/12/fas­ter-canvas-pixel-manipulation-with-typed-arrays/

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.