Python Balíčky

Programování v GIS 2

Jan Caha

2026-03-23

Modul

  • .py soubor s funkcemi, proměnnými či objekty
  • konstanty modulu obvykle zapisujeme velkými písmeny např. PI či DEFAULT_COLOR
  • např. soubor utils.py ze cvičení (a ukázek na webu)
  • lze používat lokálně
  • stačí na jednoduché použití, pro větší projekty nedostačuje

Balíček

  • složka s python soubory, která obsahuje soubor __init__.py
  • taková složka je Pythonem identifikována jako balíček (jméno složky odpovídá jménu balíčku)
  • může mít i zanořené dílčí balíčky
  • kromě kódu může obsahovat i další soubory (např. data)
  • aby Python balíček našel, musí být v některé z cest v sys.path, ty lze editovat např. skrze systémovou proměnnou PYTHONPATH
conda env config vars set PYTHONPATH=$PYTHONPATH:/path/to/your/package
python3 -c "import sys;print(sys.path);import your_package"

Příklad struktury

my_package/
├── __init__.py
├── module1.py
├── module2.py
└── subpackage/
    ├── __init__.py
    └── submodule.py
└── data/
    └── data_file.csv
    └── data.gpkg

Balíček - komplexnější

  • pokud chceme balíček i s nastavením závislostí, metadaty a testy, chceme obvykle komplexnější strukturu
  • použijeme nástroj uv – moderní a extrémně rychlý správce balíčků (napsaný v Rustu, od tvůrců Ruff)
  • instalace: conda install uv nebo pip install uv
  • uv:
    • vytvoření struktury balíčku
    • správa závislostí
    • sestavení a instalace

Balíček sestavený pomocí uv

uv init --lib nazev_balicku
nazev_balicku/
└── src/
    └── nazev_balicku/
        └── __init__.py
        └── py.typed
├── tests
    └── __init__.py
├── pyproject.toml
└── README.md

pyproject.toml

  • moderní způsob specifikace nastavení balíčku a nástrojů
  • specifikace metadata balíčku - např. název, verze, autor, závislosti
  • standard PEP 621 – nezávislý na konkrétním nástroji
[project]
name = "balicekpgis2"
version = "0.1.0"
description = "Testovací balíček pro předmět PGIS2"
authors = [
    {name = "autor", email = "autor@email.cz"}
]
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
    "gdal>=3.10.0",
    "requests>=2.32.3"
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

Přidání závislostí

  • závislosti přidáváme přímo do pyproject.toml v sekci dependencies
  • nebo pomocí příkazu uv:
uv add numpy
uv add --dev pytest black

Note

Protože používáme Conda pro správu prostředí (kvůli GDAL a dalším C závislostem), nepoužíváme uv sync – ten vytváří vlastní virtuální prostředí. Místo toho instalujeme do conda prostředí přímo.

pyproject.toml úprava přidáním dat k balíčku

  • pokud balíček obsahuje datové soubory (GeoPackage, TIF atd.), je nutné je explicitně zahrnout
[tool.hatch.build.targets.wheel]
packages = ["src/nazev_balicku"]

[tool.hatch.build.targets.wheel.force-include]
"src/nazev_balicku/data" = "nazev_balicku/data"

Přístup k datům v balíčku

  • data přibalená k balíčku je nutné načítat relativně vůči umístění balíčku
  • nikdy nepoužívat absolutní cesty ani Path.cwd() – balíček může být nainstalovaný kdekoliv
  • využíváme Path(__file__).parent pro zjištění umístění aktuálního modulu
import pathlib

# adresář s datovými soubory balíčku
_DATA_DIR = pathlib.Path(__file__).parent / "data"


def data_file_path(filename: str) -> pathlib.Path:
    """Vrátí cestu k datovému souboru v balíčku."""
    path = _DATA_DIR / filename
    if not path.exists():
        raise FileNotFoundError(f"Data file not found: {path}")
    return path


def read_text_file(filename: str) -> str:
    """Načte obsah textového souboru z datového adresáře balíčku."""
    path = data_file_path(filename)
    return path.read_text(encoding="utf-8")

Pozor

Cesty konstruované pomocí Path.cwd() nebo pevně zapsané cesty fungují pouze na vašem počítači. Balíček musí fungovat na jakémkoliv systému proto vždy relativně vůči __file__.

Verzování balíčku

  • verze se řídí konvencí Semantic Versioning (MAJOR.MINOR.PATCH)
    • MAJOR – nekompatibilní změny API (např. 1.0.0 2.0.0)
    • MINOR – nová funkcionalita, zpětně kompatibilní (např. 1.0.0 1.1.0)
    • PATCH – opravy chyb (např. 1.0.0 1.0.1)
  • verze 0.x.y signalizuje počáteční vývoj – API se může měnit
  • verze se uvádí v pyproject.toml v sekci [project]

Testování balíčku

  • složka tests/ je součástí struktury balíčku
  • knihovna pytest – jednoduchý a rozšířený nástroj pro testování
# tests/test_modul_path.py
from nazev_balicku.modul_path import fn_1


def test_fn_1_basic():
    """Test základní funkcionality."""
    result = fn_1("vstup")
    assert result is not None
    assert isinstance(result, str)
  • spuštění: pytest (v aktivním conda prostředí)
  • testy ověřují, že kód funguje správně i po změnách

Instalace do conda prostředí

conda activate pgis2
uv pip install -e .
  • tzv. editovatelná (interaktivní) instalace – změny v kódu se projeví při příštím spuštění Pythonu
  • parametr -e = editable, balíček se “odkazuje” na zdrojový kód místo kopírování
  • uv pip je výrazně rychlejší než běžný pip

Sestavení pro instalaci jinde

uv build
  • vznikne složka dist/ s balíčkem
  • balíček je ve formátu .tar.gz a .whl
  • balíček je možné nahrát na PyPI (Python Package Index) - veřejný repozitář balíčků
  • balíček je možné instalovat z .whl souboru pomocí uv pip install nazev_balicku*.whl

Použití - struktura balíčku

─── src/
    └── nazev_balicku/
        └── __init__.py
        └── py.typed
        └── modul_a.py
        └── modul_b.py
        └── data/
            └── soubor.txt

Použití - import

import nazev_balicku  # import celého balíčku (využívá __init__.py)
from nazev_balicku.modul_a import fn_1  # konkrétní funkce
from nazev_balicku.modul_b import MyClass  # konkrétní třída

nazev_balicku.fn_1()  # použití funkce

Použití - __init__.py

  • z dílčích modulů importujeme třídy a funkce do __init__.py
  • tím je zpřístupníme přímo na úrovni balíčku
  • uvnitř balíčku používáme relativní importy (from .modul import fn)
# __init__.py
from .modul_a import fn_1, fn_2
from .modul_b import MyClass

Použití - po úpravě __init__.py

  • import nazev_balicku – zpřístupní vše z __init__.py
from nazev_balicku import MyClass, fn_1

# přímé použití bez specifikace modulu
result = fn_1("vstup")
obj = MyClass()

uv poetry

uv poetry
Rychlost Extrémně rychlý (Rust) Pomalý (Python)
pyproject.toml Standardní PEP 621 Proprietární sekce [tool.poetry]
Build backend Libovolný (hatchling, setuptools) Vlastní (poetry-core)
Správa prostředí uv pip do existujícího env Vlastní virtualenv
  • uv je novější a rychlejší nástroj od tvůrců Ruff
  • poetry je starší a stále rozšířený – setkáte se s ním v existujících projektech

Závěr

  • balíčky a moduly jsou důležitou součástí Pythonu
  • umožňují strukturovat kód a znovu ho použít
  • umožňují i sdílet kód s ostatními
  • uv je moderní nástroj pro správu balíčků a závislostí
  • pyproject.toml jako standardní konfigurační soubor (PEP 621)

Dotazy?