Obsah
1. PyWebIO: interaktivní webové dialogy a formuláře naprogramované v čistém Pythonu
2. Klasické knihovny pro tvorbu GUI: systém událostí popř. signálů+slotů
3. Koncept vstupu a výstupu (I/O) namísto architektury založené na systému událostí
5. Zobrazení informací na webové stránce – modul pywebio.output
7. Informace o probíhajících operacích, zobrazení zprávy
8. Zobrazení fragmentu dokumentu zapsaného v HTML, Markdownu i ve formě zdrojového kódu
10. Animace zobrazená při načítání nebo v průběhu výpočtu
12. Sdružení několika vstupních polí do jediného formuláře
13. Specifikace typu vstupních hodnot, rozlišení povinných a nepovinných hodnot
14. Rádiová tlačítka (přepínače)
16. Výběr z několika nabízených variant
19. Repositář s demonstračními příklady
1. PyWebIO: interaktivní webové dialogy a formuláře naprogramované v čistém Pythonu
Jak již bylo napsáno v perexu dnešního článku, existují situace, kdy vývojář potřebuje vytvořit aplikaci s formuláři a dialogy, popř. i s grafy, tedy aplikaci s grafickým uživatelským rozhraním. V případě, že používá programovací jazyk Python, je možné pro tento účel využít již popsané knihovny Tkinter, PyObject, PyQt/PySide atd. (viz též seznam článků vydaných v rámci seriálu o grafickém uživatelském rozhraní v Pythonu). Alternativně je ovšem možné vytvořit lokálně či vzdáleně použitelnou webovou aplikaci, a to čistě v Pythonu: tedy bez explicitní práce s HTML, CSS a JavaScriptem. Pro tento účel poměrně dobře poslouží hned několik zajímavých knihoven a frameworků. My se dnes zaměříme na asi vůbec nejsnadněji použitelnou knihovnu nazvanou velmi příhodně PyWebIO.

Obrázek 1: Obrazovka nástroje Pygubu designer určeného pro návrh grafického uživatelského rozhraní aplikací vytvářených v Pythonu. Výsledkem je kód založený na knihovně Tkinter.
Na tomto místě se ve stručnosti zmiňme o dvou projektech s podobným cílem. První z těchto projektů se jmenuje Streamlit a budeme se jím zabývat v samostatném článku. A druhý podobný projekt se jmenuje pglet (ten dokonce podporuje větší množství programovacích jazyků).

Obrázek 2: Jednoduchá aplikace využívající knihovnu PySide.
2. Klasické knihovny pro tvorbu GUI: systém událostí popř. signálů+slotů
Většina knihoven určených pro tvorbu grafického uživatelského rozhraní (v Pythonu) je založena buď na systému událostí nebo na takzvaných signálech a slotech. V obou případech se na jednu stranu jedná o velmi flexibilní způsob tvorby GUI, ovšem při tvorbě jednodušších formulářů a dialogů může být tato flexibilita někdy na obtíž, protože se architektura aplikace musí (alespoň do jisté míry) přizpůsobit celému konceptu GUI. Ostatně si to můžeme ukázat na jednoduchém příkladu naprogramovaném s využitím snad nejsnadněji použitelné „klasické“ knihovny pro tvorbu GUI. Jedná se o knihovnu nazvanou AppJar:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: app.infoBox("Ok, Ok", "Ok button pressed") app = gui() app.addLabel("title", "Hello world!", colspan=2) app.addButtons(["Ok", "Quit"], onButtonPress, 1, 0) app.go()

Obrázek 3: Screenshot jednoduché aplikace představované předchozím skriptem.
V knihovně PySide naproti tomu může každý ovládací prvek (widget) generovat signály, a to konkrétně v případě vzniku nějaké události (tou může být například stisk tlačítka, změna pozice posuvníku, změna velikosti okna atd.) nebo změny stavu widgetu. Signály mohou být napojené na takzvané sloty, což je pojmenování pro funkce, které mohou reagovat na příchozí signál. V knihovně Qt, nad níž je PySide postaven, jsou signály zpracovávány nativními funkcemi, PySide ovšem celý koncept signálů a slotů dokáže „obalit“ takovým způsobem, že sloty jsou běžnými Pythonovskými funkcemi či metodami. Musíme však explicitně specifikovat propojení mezi signálem (resp. jeho typem) a slotem:
#!/usr/bin/env python # vim: set fileencoding=utf-8 import sys # import "jádra" frameworku Qt i modulu pro GUI from PySide import QtCore from PySide import QtGui # callback funkce def closeApplication(): print("Closing...") sys.exit(0) # nový widget bude odvozen od obecného widgetu class MainWindow(QtGui.QWidget): def __init__(self): # zavoláme konstruktor předka super(MainWindow, self).__init__() # konfigurace GUI + přidání widgetu do okna self.prepareGUI() def prepareGUI(self): self.resize(320, 240) self.setWindowTitle("Quit Button") # tlačítko button = QtGui.QPushButton("Quit", self) button.resize(button.sizeHint()) button.setToolTip("Immediately quit this application") # navázání akce na signál button.clicked.connect(closeApplication) def run(self, app): # zobrazení okna na obrazovce self.show() # vstup do smyčky událostí (event loop) app.exec_() def main(): app = QtGui.QApplication(sys.argv) MainWindow().run(app) if __name__ == '__main__': main()

Obrázek 4: Tlačítko umístěné v oknu předchozího příkladu.
3. Koncept vstupu a výstupu (I/O) namísto architektury založené na systému událostí
Knihovna PyWebIO je navržena takovým způsobem, aby vývojáře v co největší míře odstínila od nutnosti „otočení“ logiky aplikace, a to jen proto, aby v ní bylo bylo možné použít grafické uživatelské rozhraní. Autoři se naopak snažili o to, aby byla v programovém kódu zachována původní logika typu „dotaz na údaje zadávané uživatelem“ → „výpočet a odpověď vypsaná uživateli“. Jedná se o koncept, na němž je postavena klasická příkazová řádka a částečně i nástroje typu „diář“, tedy například Jupyter Notebook.
Podívejme se nyní na triviální skript napsaný v Pythonu, po jehož spuštění se počítač uživatele (postupně) zeptá na zadání vstupních hodnot. Na základě těchto hodnot je proveden výpočet a výsledek je zobrazen do terminálu. Povšimněte si, že počítač v tomto případě vede s uživatelem dialog, jenž je řízený skriptem. Jedná se skutečně o triviální příklad, v němž nemá uživatel žádnou možnost dalšího ovlivnění výpočtu (na rozdíl od většiny aplikací ovládaných z příkazového řádku, kde je naopak většinou vše řízeno uživatelem):
# Body Mass Index calculator print("Mass (kg): ") mass = int(input()) print("Height (cm): ") height = int(input()) # převod výšky na metry height = height / 100.0 # výpočet (bez jakýchkoli kontrol) bmi = mass / (height * height) # výpis výsledku print("BMI = ", bmi)

Obrázek 5: Dialog počítače s uživatelem.
Tento příklad lze snadno převést do formy využívající knihovnu PyWebIO. V případě, že vynecháme příkaz import (ten je zde ovšem nezbytný), spočívá celý přepis skriptu pouze v náhradě funkce print za funkci put_text. Žádné další úpravy nejsou nutné – a přece je výsledkem interaktivní „webová aplikace“(!):
# Body Mass Index calculator put_text("Mass (kg): ") mass = int(input()) put_text("Height (cm): ") height = int(input()) # převod výšky na metry height = height / 100.0 # výpočet (bez jakýchkoli kontrol) bmi = mass / (height * height) # výpis výsledku put_text("BMI = ", bmi)

Obrázek 6: Webové rozhraní skriptu se zobrazeným textem.
Na základě této ukázky by se mohlo zdát, že PyWebIO pouze umožňuje změnit způsob chování interaktivního vstupu (funkce input) a výstupu (funkce print), zatímco samotný skript nebude mít možnost žádným dalším způsobem ovlivnit vzhled webové aplikace například během výpočtu. Ovšem ve skutečnosti jsou možnosti PyWebIO širší, což naznačuje následující skript, jenž zobrazí „teploměr“ (tedy neinteraktivní prvek uživatelského rozhraní), jehož hodnota postupně roste on 0 do 100% (v tomto konkrétním případě jsou výpočty simulovány funkcí time.sleep – tu by však pochopitelně bylo možné nahradit reálným kódem):
put_processbar('bar'); for i in range(1, 11): set_processbar('bar', i / 10) time.sleep(0.1)
Na tomto místě je dobré upozornit na fakt, že je zřejmé, že koncept založený na prostém vstupu a výstupu není dostatečně obecný, aby se s jeho využitím mohly tvořit i aplikace se složitěji pojatým ovládáním (například webové hry nebo plně interaktivní aplikace typu Google Doc). Ovšem až překvapivé množství webových aplikací se skutečně skládá ze sady formulářů a dialogů. Příkladem jsou servery typu Root.cz s možností zadání jednoduché ankety, ale například i webová aplikace určená pro vyplňování daňových přiznání. PyWebIO je navíc určeno nikoli pouze pro tvorbu výše zmíněných „plnohodnotných“ webových aplikací, ale je například oblíben vývojáři z oblasti strojového učení (machine learning), kde je mnohdy potřeba zadat vstupní parametry a následně například vykreslit výsledek analýz či výpočtů (navíc mohou být odborníci na strojové učení odstíněni od „pohyblivých cílů“ typu Angular/React/Vue atd.).
4. Instalace knihovny PyWebIO
Knihovna PyWebIO je nabízena přes PyPi, takže její instalace by měla být jednoduchá a přímočará. Knihovnu nainstalujeme pro aktuálně přihlášeného uživatele:
$ pip3 install --user pywebio Collecting pywebio Downloading pywebio-1.5.2.tar.gz (450 kB) |████████████████████████████████| 450 kB 953 kB/s Preparing metadata (setup.py) ... done Collecting tornado>=5.0 Downloading tornado-6.1-cp38-cp38-manylinux2010_x86_64.whl (427 kB) |████████████████████████████████| 427 kB 1.6 MB/s Collecting user-agents Downloading user_agents-2.2.0-py3-none-any.whl (9.6 kB) Collecting ua-parser>=0.10.0 Downloading ua_parser-0.10.0-py2.py3-none-any.whl (35 kB) Building wheels for collected packages: pywebio Building wheel for pywebio (setup.py) ... done Created wheel for pywebio: filename=pywebio-1.5.2-py3-none-any.whl size=459628 sha256=3a86f8dfcb5992e4f1cd5c76cede3aceecaf25d07edde9f57848824cb6500c0c Stored in directory: /home/ptisnovs/.cache/pip/wheels/e7/dc/43/f395fa089831aeb5fa3eb3c577ec3ea53636b45fb03a32c301 Successfully built pywebio Installing collected packages: ua-parser, user-agents, tornado, pywebio Successfully installed pywebio-1.5.2 tornado-6.1 ua-parser-0.10.0 user-agents-2.2.0
5. Zobrazení informací na webové stránce – modul pywebio.output
Knihovna PyWebIO je rozdělena do několika balíčků (modulů). Nejprve se seznámíme se základními vlastnostmi balíčku nazvaného pywebio.output. Jak již název tohoto balíčku naznačuje, je určen pro zajištění výstupu informací přes webové rozhraní (tedy přes dynamicky generovanou a postupně aktualizovanou webovou stránku). Nejjednodušší je výstup (zobrazení) textu, což je realizováno funkcí nazvanou put_text. V nejjednodušší podobě může textový výstup vypadat následovně:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out out.put_text("Hello world!")
Po spuštění tohoto skriptu by se mělo otevřít okno s webovým prohlížečem popř. (pokud je již prohlížeč spuštěn) by se měl otevřít nový tab, jenž bude obsahovat pouze zprávu zobrazenou uživateli:

Obrázek 7: Webové rozhraní skriptu se zobrazeným textem.
Traceback (most recent call last): File "13_input.py", line 11, in <module> mass = int(inp.input()) File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/input.py", line 257, in input return single_input(item_spec, valid_func, preprocess_func, onchange_func) File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/session/__init__.py", line 283, in inner return run_as_function(gen) File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/utils.py", line 296, in run_as_function res = gen.send(res) File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/io_ctrl.py", line 260, in single_input data = yield input_control(spec=spec, File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/session/__init__.py", line 283, in inner return run_as_function(gen) File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/utils.py", line 296, in run_as_function res = gen.send(res) File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/io_ctrl.py", line 280, in input_control data = yield input_event_handle(item_valid_funcs, form_valid_funcs, preprocess_funcs, onchange_funcs) File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/session/__init__.py", line 283, in inner return run_as_function(gen) File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/utils.py", line 296, in run_as_function res = gen.send(res) File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/io_ctrl.py", line 334, in input_event_handle event = yield next_client_event() File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/session/__init__.py", line 283, in inner return run_as_function(gen) File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/utils.py", line 296, in run_as_function res = gen.send(res) File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/session/__init__.py", line 290, in next_client_event res = yield get_current_session().next_client_event() File "/home/ptisnovs/.local/lib/python3.8/site-packages/pywebio/session/threadbased.py", line 138, in next_client_event raise SessionClosedException pywebio.exceptions.SessionClosedException
6. Tabulky
Velmi často je nutné vhodnou formou zobrazit výsledek nějakého výpočtu či simulace, přičemž tento výsledek má tabulární podobu (typicky se jedná o 2D tabulku). Knihovna PyWebIO pochopitelně podporuje i zobrazení tabulárních dat. Taková data mohou být v programovacím jazyce Python reprezentována například jako seznam seznamů, seznam n-tic, jako vnořené n-tice atd. Zobrazení obsahu těchto datových struktur na dynamicky vytvářené a aktualizované webové stránce je triviální – viz též zdrojový kód dnešního druhého demonstračního příkladu:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out out.put_table([ ['Language', 'Ratings'], ['C', '15.95'], ['Java', '13.48'], ['Python', '10.47'], ['C++', '7.11'], ['C#', '4.58'], ['Visual Basic', '4.12'], ['JavaScript', '2.54'], ['PHP', '2.49'], ['R', '2.37'], ['SQL', '1.76'], ['Go', '1.46'], ['Swift', '1.38'], ['Perl', '1.30'], ['Assembly language', '1.30'], ['Ruby', '1.24'], ['MATLAB', '1.10'], ['Groovy', '0.99'], ['Rust', '0.92'], ['Objective-C', '0.85'], ['Dart', '0.77'], ])

Obrázek 8: Webové rozhraní skriptu se zobrazenou tabulkou.
Namísto statických dat použitých v předchozím příkladu je pochopitelně možné zobrazit i výsledek nějakého výpočtu, což je ukázáno v dalším skriptu:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out values = [(x, 1.0/x) for x in range(1, 20)] out.put_table(values)

Obrázek 9: Webové rozhraní skriptu se zobrazenou tabulkou.
Data v tabulce lze v případě potřeby i naformátovat:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out values = [(x, "{:5.3f}".format(1.0/x)) for x in range(1, 20)] out.put_table(values)

Obrázek 10: Webové rozhraní skriptu se zobrazenou tabulkou.
7. Informace o probíhajících operacích, zobrazení zprávy
Mezi další pasivní ovládací prvky, které lze na webové stránce použít, jsou prvky, které uživatele vizuálně informují o probíhající operaci (například o výpočtu, načítání dat atd.). U těchto prvků je možné volit jednu z osmi logických jmen barev:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out for color in ('primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'): out.put_text(color, color) out.put_loading(shape='border', color=color)

Obrázek 11: Webové rozhraní skriptu s osmi zobrazenými prvky s informací o probíhající (prozatím nedokončené) operaci.
V mnoha případech je nutné zobrazit uživateli zprávu s určitým významem (sémantikou). V knihovně PyWebIO lze vypsat informační zprávy, dále zprávu o úspěšně dokončené operaci, zprávu s varováním i zprávu o chybě. Výpis těchto zpráv je stejně snadný jako výpis běžného textu – liší se jen jméno použité funkce:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out out.put_info("Info message") out.put_success("Success message") out.put_warning("Warning message") out.put_error("Error message")

Obrázek 12: Čtyři typy zpráv podporovaných knihovnou PyWebIO.
8. Zobrazení fragmentu dokumentu zapsaného v HTML, Markdownu i ve formě zdrojového kódu
Část údajů zobrazená ve webové aplikaci může být zapsána přímo v HTML (například se může jednat o část vytvořenou nějakým šablonovacím systémem). Pro zobrazení fragmentu HTML se používá výstupní funkce put_html:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out html = """ <h1>Header</h1> <table> <tr> <td style='background:#ff8080'>Cell</td> <td style='background:#ffff80'>Cell</td> </tr> </table> """ out.put_html(html)

Obrázek 13: Fragment HTML zobrazený ve webové aplikaci.
Stejně snadno lze zobrazit dokument napsaný v Markdownu. Namísto funkce put_html se v tomto případě použije funkce nazvaná put_markdown:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out markdown = ''' Markdown rendering ================== Lorem ipsum ----------- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ''' out.put_markdown(markdown)

Obrázek 14: Dokument zapsaný v Markdownu zobrazený ve webové aplikaci.
A konečně je možné ve webové aplikaci zobrazit zdrojový kód s obarvenou syntaxí. Pro tento účel se používá funkce put_code, které se předává i jméno jazyka, v němž jsou zdrojové kódy zapsány:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out code = """ # Body Mass Index calculator print("Mass (kg): ") mass = int(input()) print("Height (cm): ") height = int(input()) # předod výšky na metry height = height / 100.0 # výpočet (bez jakýchkoli kontrol) bmi = mass / (height * height) # výpis výsledku print("BMI = ", bmi) """ out.put_code(code, language="python", rows=15) code2 = r""" package main import "fmt" // I represents a new interface type (in this case empty interface) type I interface{} // T represents an user-defined data type type T struct{} func main() { var t *T if t == nil { fmt.Println("t is nil") } else { fmt.Println("t is not nil") } var i I = t if i == nil { fmt.Println("i is nil") } else { fmt.Println("i is not nil") } } """ out.put_code(code2, language="go", rows=15)

Obrázek 15: Dva zdrojové kódy zobrazené ve webové aplikaci.
9. Animace průběhu výpočtu
Se způsobem zobrazení animace ve chvíli, kdy se načítají data nebo se provádí výpočet, jsme se již setkali, takže si jen v krátkosti připomeňme, že pro tento účel se používá ovládací prvek process bar, jehož aktuální hodnotu v rozsahu 0 až 1 je možné programově měnit. V případě potřeby je možné využít i větší množství těchto ovládacích prvků (například pro zobrazení průběhu dílčích operací):
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out import time out.put_processbar('bar'); for i in range(1, 11): out.set_processbar('bar', i / 10) time.sleep(0.1)

Obrázek 16: Animace průběhu výpočtu.
10. Animace zobrazená při načítání nebo v průběhu výpočtu
V případě, že není zřejmé, jak dlouho má nějaká operace trvat (a tedy není možné použít processbar), lze využít ovládací prvek nazvaný loading, který na ploše webové aplikace zobrazí animaci oznamující, že probíhá nějaká operace. Po dokončení této operace se v aktuálním kontextu pouze vypíše informace o dokončení (či jakákoli další data), jak je ukázáno v následujícím příkladu (s kontextem lze v Pythonu nejsnáze pracovat s využitím bloku with):
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out import time with out.put_loading(shape='border', color='primary'): time.sleep(5) out.put_text("Done")

Obrázek 17: Jeden snímek animace zobrazené při načítání nebo v průběhu výpočtu.
Podporovány jsou i sémantické názvy barev:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.output as out import time i = 0 for color in ('primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'): with out.put_loading(shape='border', color=color): time.sleep(1) out.put_text(i) i += 1 out.put_text("Done")

Obrázek 18: Specifikace barvy prvku.
11. Vstupní textové pole
Pro vstup textových popř. pouze číselných údajů slouží vstupní textové pole, které se zobrazuje funkcí s plným jménem pywebio.input.input. V případě, že je tato funkce zavolána, zobrazí se na webové stránce vstupní pole a teprve po zadání a potvrzení údajů bude program pokračovat dalším zapsaným příkazem. Přepis původní aplikace určené pro ovládání z terminálu do „webové podoby“ může vypadat následovně:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.input as inp import pywebio.output as out # Body Mass Index calculator out.put_text("Mass (kg): ") mass = int(inp.input()) out.put_text("Height (cm): ") height = int(inp.input()) # převod výšky na metry height = height / 100.0 # výpočet (bez jakýchkoli kontrol) bmi = mass / (height * height) # výpis výsledku out.put_info("BMI = ", bmi)

Obrázek 19: Vstupní textové pole zobrazené ve webové aplikaci.
12. Sdružení několika vstupních polí do jediného formuláře
Velmi často se setkáme s požadavkem na zadání většího množství údajů do několika vstupních polí. S využitím funkce pywebio.input.input_group je možné sdružit libovolné množství vstupních prvků, tedy i textových polí, a zobrazit je společně. Po zápisu a potvrzení údajů se vrátí slovník, jehož klíče jsou specifikovány při tvorbě vstupních polí parametrem name:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.input as inp import pywebio.output as out # Body Mass Index calculator info = inp.input_group("Entry",[ inp.input("Mass (kg)", name="mass"), inp.input("Height (cm)", name="height") ]) mass = float(info["mass"]) height = float(info["height"]) # převod výšky na metry height = height / 100.0 # výpočet (bez jakýchkoli kontrol) bmi = mass / (height * height) # výpis výsledku out.put_info("BMI = ", bmi)
Výsledkem by měl být následující formulář:

Obrázek 20: Dvojice vstupních polí sdružená do jediného formuláře.
13. Specifikace typu vstupních hodnot, rozlišení povinných a nepovinných hodnot
Mnohá vstupní pole mají akceptovat pouze omezenou množinu znaků popř. zadávaných hodnot. Příkladem může být náš skript, který po uživateli vyžaduje zápis hmotnosti a výšky. V obou případech se jedná o číselné údaje, takže má smysl omezit množinu znaků a jejich kombinací, které může uživatel v těchto dvou vstupních polích použít. Konkrétně je možné u vstupních polí specifikovat, že lze povolit pouze zadání čísel, a to s využitím nepovinného parametru type (viz zvýrazněnou část zdrojového kódu):
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.input as inp import pywebio.output as out # Body Mass Index calculator info = inp.input_group("Entry",[ inp.input("Mass (kg)", name="mass", type=inp.NUMBER), inp.input("Height (cm)", name="height", type=inp.NUMBER) ]) mass = info["mass"] height = info["height"] # převod výšky na metry height = height / 100.0 # výpočet (bez jakýchkoli kontrol) bmi = mass / (height * height) # výpis výsledku out.put_info("BMI = ", bmi)

Obrázek 21: Vstupní pole pro vstup číselných údajů.
Dále je velmi vhodné specifikovat, které vstupní hodnoty se musí vyplnit a které hodnoty jsou naopak nepovinné. K zadání této informace slouží nepovinný parametr required. Opět se podívejte na zvýrazněnou část zdrojového kódu, v níž je tento parametr použit:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.input as inp import pywebio.output as out # Body Mass Index calculator info = inp.input_group("Entry",[ inp.input("Mass (kg)", name="mass", type=inp.NUMBER, required=True), inp.input("Height (cm)", name="height", type=inp.NUMBER, required=True) ]) mass = info["mass"] height = info["height"] # převod výšky na metry height = height / 100.0 # výpočet (bez jakýchkoli kontrol) bmi = mass / (height * height) # výpis výsledku out.put_info("BMI = ", bmi)

Obrázek 22: Vstupní pole, které je nutné vyplnit.
14. Rádiová tlačítka (přepínače)
Dalším velmi často používaným ovládacím prvkem (přesněji řečeno specializovanou variantou tlačítka) je takzvaný Radiobutton (přepínač). Tento typ widgetu se od klasických tlačítek (Button) odlišuje především tím, že je používán ve větších skupinách. Z každé skupiny přitom může být vybrán (nastaven) pouze jeden přepínač, od čehož je ostatně odvozen původní anglický název tohoto ovládacího prvku, protože připomíná přepínač kanálů na starších rádiích. Rádiová tlačítka jsou podporována i knihovnou PyWebIO, o čemž se ostatně můžeme velmi snadno přesvědčit spuštěním následujícího skriptu. Měl by se zobrazit jednoduchý formulář s třemi nabídkami a taktéž s tlačítky Submit a Reset:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.input as inp import pywebio.output as out answer = inp.radio(label="test", options=["varianta 1", "varianta 2", "varianta 3"]) out.put_info("Odpověď") out.put_text(answer)

Obrázek 23: Přepínače zobrazené ve webové aplikaci.
15. Výběrové boxy
Dalším typem grafického ovládacího prvku (widgetu) je takzvaný checkbutton, dnes poněkud nepřesně nazývaný checkbox. Od obyčejného tlačítka se tento widget liší především tím, že je vizuálně patrný jeho stav – nastaveno/nenastaveno. Tento typ tlačítek je zobrazován různým způsobem, typicky se však jedná o čtvereček, který je buď zatržený (znak ✓ či ×) nebo prázdný; v některých GUI prostředích se však stav tlačítka reprezentuje pouze jeho barvou. V nejjednodušším případě se přepínací tlačítko vytvoří následovně:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.input as inp import pywebio.output as out answer = inp.checkbox(label="test", options=["varianta 1", "varianta 2", "varianta 3"]) out.put_info("Odpověď") out.put_text(answer)

Obrázek 24: Výběrové boxy zobrazené ve webové aplikaci.
16. Výběr z několika nabízených variant
Výběr akce či odpovědi z několika předem známých variant lze realizovat i odlišným způsobem – použitím ovládacího prvku actions. Ve skutečnosti se v tomto případě zobrazí několik tlačítek, z nichž je (logicky) možné vybrat pouze jediné. Tlačítka se funkci actions předávají v pojmenovaném parametru buttons:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.input as inp import pywebio.output as out answer = inp.actions(label="test", buttons=["varianta 1", "varianta 2", "varianta 3"]) out.put_info("Odpověď") out.put_text(answer)

Obrázek 25: Výběrová tlačítka zobrazené ve webové aplikaci.
17. Posuvník
Poslední ovládací prvek, který si dnes popíšeme, se nazývá slider, ovšem v jiných knihovnách se například setkáme i s označením slider. Jedná se o interaktivní ovládací prvek, který uživateli umožňuje výběr hodnoty v zadaném rozsahu (a popř. i se specifikovaným krokem). Výchozí hodnota posuvníku se nastavuje parametrem value:
#!/usr/bin/env python3 # vim: set fileencoding=utf-8 import pywebio.input as inp import pywebio.output as out weight = inp.slider(label="Váha", value=75, min_value=30, max_value=150) out.put_info("Váha") out.put_text(weight)

Obrázek 26: Posuvník zobrazený ve webové aplikaci.
18. Obsah navazujícího článku
V navazujícím článku se zaměříme především na způsoby deklarace složitějších formulářů s větším množstvím vstupních prvků, dále se správou sezení (session) a taktéž na použití různých forem výstupů. Knihovnu PyWebIO je totiž možné v případě potřeby použít společně s dalšími knihovnami. Například lze relativně jednoduše realizovat vykreslení grafů do dynamicky generované webové stránky. Pro tento účel lze využít například knihovnu Matplotlib, ale taktéž knihovny Bokeh, pyecharts, plotly, pyg2plot či cutecharts.py.
19. Repositář s demonstračními příklady
Zdrojové kódy všech dnes popsaných demonstračních příkladů určených pro programovací jazyk Python 3 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:
20. Odkazy na Internetu
- Low code Python web framework
https://www.pyweb.io/ - Repositář projektu
https://github.com/pywebio/PyWebIO/ - Getting Started
https://www.pyweb.io/tutorial.html - Dokumentace
https://pywebio.readthedocs.io/en/latest/ - Why PyWebIO?
https://github.com/pywebio/PyWebIO/wiki/Why-PyWebIO%3F - PyWebIO demos
https://pywebio-demos.pywebio.online/ - PyWebIO Chart Gallery
https://pywebio-charts.pywebio.online/ - Awesome Python
https://awesome-python.com/ - A complete guide to web development in Python
https://www.educative.io/blog/web-development-in-python - Python Web Development Tutorials
https://realpython.com/tutorials/web-dev/ - What is Flask Python
https://pythonbasics.org/what-is-flask-python/ - CherryPy
https://cherrypy.dev/ - Projekt Zenity
https://wiki.gnome.org/Projects/Zenity - Nástroj Dialog
http://invisible-island.net/dialog/ - Plotly
https://plotly.com/ - Bokeh
https://bokeh.org/ - pyecharts
https://github.com/pyecharts/pyecharts/blob/master/README.en.md - 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/ - Alternatives to PyWebIO
https://stackshare.io/pywebio/alternatives - The fastest way to build and share data apps – Streamlit
https://streamlit.io/ - Dash Enterprise
https://plotly.com/dash/ - pglet
https://pglet.io/
Printscreeny použité v textu vytvořila redakce Root.cz