Opakování Pythonu

Programování v GIS 2

Jan Caha

2026-02-16

Práce s Pythonem

  • cílem je naučit se rozumné návyky a postupy při programování v Pythonu
  • předcházet nevhodným postupům, návykům a chybám, které komplikují v dlouhodobém horizontu práci
  • i když některé postupy vypadají zbytečně složité či nepotřebné, většinou se vyplatí z dlouhodobého hlediska
  • většina postupů je založena na zkušenostech a doporučeních z praxe
  • “pokud jste nějaký kód neotevřeli 3 měsíce, mohl ho klidně napsat někdo cizí” - potřebujeme tedy kód, který je srozumitelný a použitelný i po delší době a pro někoho cizího
  • věci, které jsou “navíc” děláte pro svoje budoucí já a ulehčujete mu tím práci

Python

  • interpretovaný programovací (skriptovací) jazyk
  • dynamicky typovaný
  • široce využívaný - ať už samostatně, nebo i jako součást jiného softwaru
  • snadno propojitelný s dalšími knihovnami i softwarem
  • podpora jak objektového, tak i funkcionálního programování
  • verze 2.x už nepoužívat, verze 3 ideálně od 3.12 a novější (aktuální verze a cca dvě verze zpátky)

VS Code

  • IDE pro řadu jazyků a technologií
  • klíčové jsou extenze, které posunují funkcionalitu od textového editoru více k “težšímu” IDE
  • profily - pro různé technologie či využití
  • synchronizace po přihlášení (účet GitHub)
  • instalace - lze bez administrátorských práv

VS Code extenze pro Python

  • Python, Python Debugger
  • formátování kódu - Black Formatter, isort
  • kontroly kódu - autopep8, Flake8, Mypy Type Checker, Pylance, Pylint
  • generování docstringů - autoDocstring - Python Docstring Generator
  • Github Copilot - přihlášení, pouze pokud máte přístup (studenti mají) - nově existuje i limitovaná verze zdarma

Správa Pythonu

Conda

  • systém pro správu Pythonu a jeho balíčků (informace)
  • použití z příkazové řádky - ale existuje i GUI (Anaconda)
  • oficiální a neoficiální kanály (conda-forge)
conda create -n pgis2 python=3.14
conda activate pgis2
conda config --add channels conda-forge
conda install GDAL
conda deactivate
  • v environmentu lze instalovat i skrze pip, ale nelze to doporučit - chybí návaznosti závislostí
    • má smysl pouze tehdy, pokud knihovně chybí conda balíček
  • v VS Code nutno nastavit interpretor jazyka

Proč Conda a ne venv?

  • Python má i nativní nástroj pro virtuální prostředí - venv
  • venv spravuje pouze Python balíčky instalované přes pip
  • Conda spravuje i kompilované systémové závislosti (C/C++ knihovny)
  • pro GIS knihovny (GDAL, rasterio, fiona) je to klíčové - závisí na kompilovaných knihovnách, které pip neumí správně nainstalovat
  • Conda = správa Pythonu i jeho okolí venv = pouze Python balíčky
  • v praxi: pro GIS vždy preferovat Conda, pro čistě Python projekty (web, API) může stačit venv

Instalace knihoven

conda activate pgis2
conda install black isort mypy pep8 flake8 pylint
conda install shapely fiona rasterio polars pandas geopandas
  • podle osnovy se máme věnovat pandas - polars je výrazně rychlejší implementace, novější, s lépe použitelnou syntaxí a čitelnějším kódem

Tvorba Conda prostředí

  • ideálně ne manuálně, ale z definičního souboru
  • yaml soubor s popisem prostředí (název, použité kanály, verze Pythonu, balíčky - klidně i s verzemi)
  • tvorba prostředí - conda env create -f env-pgis2.yaml - viz stránka předmětu
  • odstranění prostředí - conda env remove -n pgis2
  • je lepší prostředí odstranit, upravit definiční soubor a znovu vytvořit, než prostředí modifikovat manuálně (hrozí nekonzistence a nezaznamenání změn)

Python - použití jazyka
opakování

Proměnné

  • jednoduché - celá čísla, čísla s plovoucí desetinnou čárkou, text, pravdivostní hodnota
  • komplexní - seznam, slovník, tuple
seznam = [1, 2, 3]
slovnik = {"a": 1, "b": 2}
t = (1, 2, 3)
  • objekty - např. Path z knihovny pathlib
  • funkce - lze je také uložit do proměnné (trochu komplikované na představu)
def fun(): ...


a = fun
a()

Podmínky

  • konstrukce if, elif, else

Cykly

  • se známým počtem opakování, bez známého počtu opakování
  • konstrukce for a while
  • přeskočení iterace v cyklu continue a ukončení cyklu break
  • speciální případ for s enumerate() (iterace přes prvky seznamu, nebo slovníku a zároveň získání indexu)
  • range() - funkce pro generování číselné posloupnosti
v = ["a", "b", "c"]
for i, x in enumerate(v):
    print(f"Na pozici {i} je hodnota {x}")
Na pozici 0 je hodnota a
Na pozici 1 je hodnota b
Na pozici 2 je hodnota c

Seznamy - comprehensions

  • jednoduchá konstrukce na zpracování seznamu
  • nahrazuje cyklus, ale pouze pro jednoduché operace, jinak může být nečitelné
  • struktura - [příkaz for prvek in struktura]
values = [1, 2, 3]
modified_values = [f"cislo {x}" for x in values]
print(modified_values)
['cislo 1', 'cislo 2', 'cislo 3']
  • lze i filtrovat pomocí if
values = [1, 2, 3, 5, 6, 7]
modified_values = [str(x) for x in values if x > 4]
print(modified_values)
['5', '6', '7']

Řetězce

  • často potřebujeme spojit řetězec s hodnotou, či podobná operace
  • konstrukce f"řetězec {promenna}" - tzv. f-string, vysoce optimalizovaný způsob spojování řetězců
  • jiné varianty nepoužívat
    • "hodnota {}".format(promenna)
    • "hodnota %s" % promenna
    • "hodnota " + str(promenna)
  • tvorba řetězce z pole
    • ", ".join(["a", "b", "c"])
    • ošetří poslední hodnotu a další limitní případy

Import knihoven či modulů

  • lze importovat objekty, funkce, moduly
  • lze buď celým názvem - import pathlib
  • lokální souboru lze i jako import .muj_soubor (doporučuje se pouze u jednoduchých skriptů, v případě modulů - knihoven lépe importovat plnou cestou)
  • lze importovat i s přejmenováním - import numpy as np
  • kombinace a variace importů občas ztěžují interpretaci kódu

Chyba

Počítače mají skvělou vlastnosti, dělají co je jim zadá. Počítače maji jeden zásadní problém, dělají přesně, co se jim zadá.

  • neřešitelná situace v programu
  • nelze dál pokračovat - program se zastaví
"a" + 1
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[6], line 1
----> 1 "a" + 1

TypeError: can only concatenate str (not "int") to str

Zpracování chyb

  • druhy chyb - dokumentace
  • konstrukce try, except, finally
try:
    "a" + 1
    print("Toto se nevykoná")
except TypeError as e:
    print(f"Chyba: {e}")
finally:
    print("Konec")
Chyba: can only concatenate str (not "int") to str
Konec

Vyvolání chyby

  • konstrukce raise
  • další kód musí buď chybu zachytit a zpracovat, nebo se program zastaví
a = 5
if a > 3:
    raise ValueError("`a` nesmí být větší než 3")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[8], line 3
      1 a = 5
      2 if a > 3:
----> 3     raise ValueError("`a` nesmí být větší než 3")

ValueError: `a` nesmí být větší než 3

Magické proměnné či funkce

  • zapisují je jako __nazev__
  • odkazují na předpřipravené konstrukce (funkce, proměnné) v Pythonu a mají obvykle speciální chování
  • ukázka - tvorba objektu a funkce pro tisk
  • do této skupiny lze zařadit i soubor __init__.py, jehož existence označuje složku jako Pythonový modul

Magické metody - tisk objektu

  • tisk objektu bez funkce __repr__()
  • tiskne informace o umístění objektu v paměti
class A:
    def __init__(self):
        pass


a = A()
print(a)
<__main__.A object at 0x7f6398286e40>

Magické metody - tisk objektu

  • tisk objektu s funkcí __repr__()
  • tiskne řetězec z této funkce
class A:
    def __init__(self):
        pass

    def __repr__(self) -> str:
        return "Objekt třídy A."


a = A()
print(a)
Objekt třídy A.

Kontextové managery

  • konstrukce with
  • vztahují se k veškerému kódu uvnitř bloku (odsazení)
  • vhodné tam kde existuje nějaký logický začátek a konec operace nebo operace, které se s počátkem a koncem pevně pojí
    • např. zápis textu do souboru - soubor otevřeme, zapíšeme text a soubor zavřeme (to nemusí být explicitní, může být i “neviditelný”)
  • objekty, které využívají dvou magických metod __enter__ a __exit__
  • ukázka se souborem
  • ukázka s vlastním managerem

Kontextové managery ukázka

file = open("soubor.txt", "w")
file.write("Text")
file.close()  # na tohle se často zapomene - může/nemusí být problém
  • s kontextovým managerem
with open("soubor.txt", "w") as file:
    file.write("Text")
  • i komplexnější operace, např. připojení k databázi a uzavření spojení

Typování proměnných

  • teoreticky není vůbec nutné
  • zejména u větších knihoven však výrazně pomáhá s managementem kódu
  • zastoupí částečně i dokumentaci, protože signatura funkce nese veškeré nezbytné informace
  • při vytvoření proměnné v kódu můžeme za : uvést typ proměnné
  • obvykle hlavně u funkcí
  • za -> uvádíme návratový typ funkce

Typování proměnných - ukázka

import typing


def fun(vals: typing.List[float], round_up: bool = True) -> typing.List[int]: ...


# manuální typování proměnných, většina knihoven by a identifikovala jako int, ale chceme dát najevo, že může jít o desetinná čísla
a: float = 5
# tento zápis se už detekuje jako float, ale málokdy se to zapíše správně
b = 5.0

Typování - komplexnější 1

  • typing.Optional[] - pro proměnné, které mají buď specifickou hodnotu nebo None
    • lze zapsat i jako float | None, shodné jako typing.Optional[float]
  • typing.Union[float, int] - pro proměnné, které mohou mít více typů
  • typing.Any - pro proměnné, které mohou mít libovolný typ (většinou se snažíme vyhnout)
  • typing.Literal[] - pro proměnné, které mohou mít pouze určité hodnoty
    • používá se jako typing.Literal["a", "b"]

Typování - komplexnější 2

  • typing.Callable - pro proměnné, které jsou funkce
    • typing.Callable[[int, int], int] - funkce s dvěma vstupy (celá čísla) a jedním výstupem (celé číslo)

Objekt Path z knihovny pathlib

  • objekty cesty k souborům a složkám
  • umožňuje snadnější manipulaci s cestami
  • přepsané magické metody, umožňují spojovat cesty pomocí operátoru /
    • např. cesta = Path("slozka") / "soubor.txt"
  • umožňuje snadnější práci s cestami, než klasické operace s řetězci
  • tyto objekty lze používat na různých místech v Python knihovnách a funkcí (např. open())
  • pokud potřebujeme cestu v podobě textového řetězce, lze ji získat pomocí metody as_posix()
    • cesta_text = cesta.as_posix()

Delší skripty

  • Python pouští skripty standardně celé
    • problém se čtením u delších souborů
    • při importu se také interpretuje celý soubor (může se spustit kód, který by neměl)
  • typicky řada funkcí nasledovaná kódem, který má běžet
  • část skriptu, která se má spustit uvádět do if __name__ == "__main__":
    • tato část se spustí, pouze pokud je spuštěn soubor přímo, nikoliv importován

Delší skripty - příklad

def fn_a(): ...
def fn_b(): ...
def fn_c(): ...


a = 1 + 1  # kód, který se vykoná vždy (spuštění i import)

if __name__ == "__main__":
    # vykoná se pouze při explicitním spuštění souboru
    fn_a()
    fn_b()
    fn_c()

Formátování pomocí black a isort

  • isort řadí importy dle určité logiky
  • black formátuje kód dle pravidel, má minimum nastavení a tak je vysoce konstantní napříč projekty
  • zpočátku obvykle nevyhovuje uživateli na 100%, ale jde o zvyk

Kontroly pomocí mypy, pep8, flake8, pylint

  • zvýrazňování možných chyb, příkladů špatné praxe a dalšího v kódu
  • ne vždy musí jít o zásadní problém
  • v moha situacích to předchází chybám
  • např. mypy nutí uživatele psát rozumně typovaný kód a používat ho správně
  • celkově dodržování těchto pravidel vede k použitelnému a čitelnému kódu
  • většina těchto nástrojů má svoje nastavení a možnosti, jak je upravit
  • konkrétní hlášky lze obvykle potlačit, pokud jsou nežádoucí, buď přímo v kódu, nebo v konfiguraci nástroje

Debugování

  • závisí na použitém IDE
  • občas se nahrazuje použitím print(), ale to nemusí být dostačující
  • proces nahlížení na stav programu za jeho běhu
  • umožňuje nahlížet do paměti programu (proměnné a jejich hodnoty) v jeho různých fázích a stavech
  • breakpointy - zastavení programu v určitém místě
  • v Pythonu máme možnost do proměnných za běhu i zasahovat
  • ukázka v VS Code

Dotazy?