Python environment a balíčkovací systémy

Jedna věc, která usnadňuje vývojáři život, je možnost využití už existujícího kódu, který napsal někdo před ním. Kódu, který je udržovaný, otestovaný, použitý na různých projektech a tím pádem má vychytané i mouchy, na které by si jinak každý musel přijít sám. Takovému kódu, který napsal někdo před námi a řeší konkrétní úlohu, se říká balíček nebo knihovna.

Většina veřejných python balíčků bývá nahrána v repozitáři, kterému se říká PyPI (python package index - pypi.org). Nástroje jako pip nebo poetry, o kterých si v článku povíme něco víc, je dokážou snadno stáhnout do lokálního adresáře knihoven a váš python skript s nimi v tu chvíli může začít pracovat.

Není neobvyklé, že i malé python projekty mají několik jednotek až desítek závislostí na externích knihovnách. Pokud takových projektů potřebujete na svém stroji vyvíjet a spustit více, můžete narazit na problém, že jeden z nich bude vyžadovat například knihovnu XY ve verzi 2.0 a jiný ve verzi 3.0. Jak váš projekt pozná, kterou verzi použít? A je vůbec možné mít staženo více verzí zároveň? K vyřešení tohoto problému se využívá něco, čemu se říká python environment, případně virtual environment. Virtual environment nám umožňuje vytvořit lokální adresář s prostředím, ve kterém se náš projekt bude spouštět. V tomto adresáři máme typicky definovaný správný výchozí python interpreter a knihovny přesně v takových verzích, které náš projekt vyžaduje. Díky tomuto přístupu si jednak nezaneřádíme systémový adresář s knihovnami a navíc krásně vyřeší problém, kdy každý projekt vyžaduje jinou verzi dané knihovny.

pip a virtualenv

Níže uvedený návod a příklady budou předpokládat operační systém Linux nebo MacOS. Pro Windows budou příkazy dost podobné, budou se lišit pouze v detailech.

Pokud ještě nemáte nainstalovaný modul pip (můžete oveřit spuštěním, případně zavoláním which pip), začneme jeho instalací. Nejsnadnější způsob je postupovat podle návodu na stránkách pip.pypa.io a stáhnout a spustit skript get-pip.py.

wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py

Pomocí pipu si, tentokrát ještě do globálního adresáře knihoven, zkusíme nainstalovat modul virtualenv

pip install virtualenv

Teď se konečně můžeme pustit do vytvoření virtuálního prostředí. To vyžaduje vytvoření adresáře, kde budou uloženy všechny potřebné knihovny pro běh naší aplikace. Doporučuji tento adresář držet "blízko" projektu samotného, případně ho správně pojmenovat. Pokud máme například projekt uložen v adresáři ~/projects/myapp/, hodí se vyrobit zanořenější strukturu:

projects/
└── myapp
    └── myapp

a v prvním adresáři myapp vyrobit adresář pro náš virtualenv. Přejdeme proto do adresáře ~/projects/myapp a spustíme příkaz:

virtualenv -p python3 venv

Přepínačem -p jsme řekli, jaký interpreter (verzi pythonu) budeme v našem virtuálním prostředí používat a venv je název samotného adresáře, ve kterém budou uloženy knihovny používané v rámci vytvořeného virtuální prostředí. Naše adresářová struktura teď bude vypadat takto:

projects/
└── myapp
    ├── myapp
    └── venv

Virtual environment máme vytvořený, ale kdybychom si teď spustili python interpreter, pořád by pracoval a instaloval knihovny pouze globálně. Virtual environment je potřeba ještě aktivovat.

source ~/projects/myapp/venv/bin/activate

Opět budeme předpokládat, že jsme na Linuxu nebo MacOS. Příkaz source nám načte a spustí všechno z bash skriptu activate, který se stará o správné nastavení cest a interpreter. Virtualenv můžeme deaktivovat příkazem deactivate. Když teď spustíme příkaz python nebo nainstalujeme novou knihovnu přes pip, automaticky se přidá do adresáře venv. Pokud budeme chtít svou aplikaci distribuovat, dojde k poškození některého z balíčku apod., není nic snadnějšího než adresář venv smazat, vytvořit virtualenv znovu a nainstalovat všechny potřebné závislosti.​​​​​​

Základní pip příkazy

  • pip install [nazev_balicku]
    • Příkaz nainstaluje balíček z indexu (pypi.org)
  • pip install -r [cesta_k_souboru]
    • Každý projekt většinou obsahuje více závislostí. Aby bylo jasné, které to jsou, bývají uložené v souboru requirements.txt, nejčastěji včetně zamražené (freeznuté) verze. Tento soubor můžeme poslat do příkazu pip install a nainstalovat tak všechny obsažené balíčky najednou.
  • pip uninstall [nazev_balicku]
    • Odinstaluje konkrétní balíček
  • pip list
    • Zobrazí seznam všech nainstalovaných python balíčků
  • pip show [nazev_balicku]
    • Zobrazí metadata k požadovanému balíčku (verze, autor, umístění, ...)

Pokud je z nějakého důvodu potřeba nakonfigurovat pip klienta, můžete vytvořit/editovat soubor v umístění ~/.pip/pip.conf a říct například pomocí konfigurace níže, že chcete použít jinou pypi registry, než výchozí.

[global]
index-url = https://moje-pypi.xy/simple/

Poetry

Poetry je moderní alternativa k virtualenvu a pipu. Zahrnuje v sobě jak funkci virtuálního prostředí, tak package management. Poetry si můžeme na Linux/OSX nainstalovat podobně jako pip pomocí jednoho příkazu:

curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -

Pokud vytváříme zbrusu nový projekt, na kterém chceme využít Poetry, spustíme příkaz:

poetry new muj-projekt

Tímto se nám vytvoří nový adresář muj-projekt s následující strukturou:

muj-projekt/
├── README.rst
├── muj_projekt
│   └── __init__.py
├── pyproject.toml
└── tests
    ├── __init__.py
    └── test_muj_projekt.py

V tuto chvíli nás bude zajímat soubor pyproject.toml. Jedná se o soubor s metadaty projektu, ve kterém najdeme základní informace o názvu, verzi, autorovi a pak především závislostech a nastavení konkrétních nástrojů, které v rámci projektu využíváme (například Black nebo právě Poetry).

[tool.poetry]
name = "muj-projekt"
version = "0.1.0"
description = ""
authors = ["Joe Doe"]

[tool.poetry.dependencies]
python = "^3.9"

[tool.poetry.dev-dependencies]
pytest = "^5.2"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

Pokud máme už existující projekt, na kterém chceme Poetry využít, přejdeme do adresáře s projektem a spustíme příkaz poetry init. Pokud v projektu neexistuje soubor pyproject.toml, Poetry ho vytvoří.

Poetry v sobě má podporu virtuálního prostředí. Když spustíte příkaz poetry shell, automaticky se toto prostředí spustí. Pokud teď spustíme python, případně nainstalujeme nějaký balíček, automaticky se přidá do vytvořeného virtuálního prostředí. Na rozdíl od virtualenvu, si nedefinujeme adresář s prostředím (samozřejmě můžeme pokud chceme), ale po prvním spuštění poetry shell se automaticky vytvoří v definovaném adresáři (virtualenvs.path), který si případně můžeme nastavit podle sebe příkazem poetry config. Pokud nás zajímá cesta k virtuálnímu prostředí, je užitečný příkaz poetry env info --path, který cestu vypíše. Tam najdeme například soubor bin/activate, podobně jako u virtualenvu, který si můžeme podle potřeby modifikovat.

Pro přidání nového balíčku do projektu použijeme příkaz poetry add [nazev_balicku]. Takový balíček se přidá automaticky do závislostí v souboru pyproject.toml včetně specifické verze.

Seznam užitečných příkazů

  • poetry init
    • Nainicializuje poetry a vytvoří pyproject.toml v již existujícím projektu
  • poetry new [nazev_projektu]
    • Vytvoří adresář nazev_projektu se základní kostrou a poetry prostředím
  • poetry shell
    • Nastartuje virtuální prostředí, ve kterém můžete spouštět svoj aplikaci.
  • poetry config --list
    • Zobrazí aktuální konfiguraci poetry
  • poetry env info --path
    • Zobrazí cestu, ve které se nachází virutální prostředí vyrobené poetry
  • poetry add [nazev_balicku]
    • Nainstaluje balíček nazev_balicku a přidá jej do souboru pyproject.toml
Úroveň znalostí
Začátečník