Zpět na domů

Architektura venv v Pythonu: jak pyvenv.cfg řídí sys.path

Článek vysvětluje, jak virtuální prostředí v Pythonu zajišťují izolaci závislostí na úrovni CPython prostřednictvím souboru pyvenv.cfg a přepočtu sys.path. Zkoumá nízkourovňovou architekturu, minimální požadavky na prostředí a metody diagnostiky.

Jak CPython čte pyvenv.cfg a izoluje závislosti
Advertisement 728x90

Architektura izolace virtuálních prostředí v CPythonu: pyvenv.cfg a nízkourovňová logika sys.path

Virtuální prostředí v Pythonu nejsou abstrakcí, ale přesně definovaným systémem interakce mezi souborovou soustavou, konfigurací a C-kódem interpretátora. Jejich izolace se nedosahuje pomocí kontejnerizace ani přechytávání importů, ale díky deterministické změně chování načítadla modulů během inicializace. To je kriticky důležité pro reprodukovatelné buildy, CI/CD a multi‑projektové prostředí.

Proč je virtualenv zastaralý a venv funguje bez pipu

Do verze Pythonu 3.3 byla izolace externím úkolem: virtualenv kopíroval binární soubor interpretátora, duplikoval standardní knihovnu a patchoval sys.path pomocí obalů. To zpomalilo vytváření prostředí, zvětšilo disku a zkomplikovalo ladění. S příchodem PEP 405 byl tento mechanismus integrován do jádra CPythonu. Klíčový rozdíl spočívá v opuštění kopírování binárního souboru ve prospěch symbolických odkazů (Linux/macOS) nebo launcherů (Windows), což činí venv okamžitým a závislým pouze na nainstalovaném Pythonu.

Hlavní technický posun spočívá v přenesení logiky zvenčí do samotného interpretátora. Místo toho, aby se Python „obloupal“ pomocí proměnných prostředí nebo shellových obalů, venv spoléhá na interní algoritmus vyhledávání pyvenv.cfg. Tento soubor je jediným spouštěčem, který nutí CPython přeformátovat sys.path a deaktivovat globální site-packages.

Google AdInline article slot

Jak CPython čte pyvenv.cfg a přepočítává sys.path

Inicializace probíhá na úrovni C‑kódu načítadla (Py_Initialize). Při spuštění spustitelného souboru interpretátor provede následující postup:

  • Určí umístění spustitelného souboru (například /project/.venv/bin/python).
  • Vystoupá po hierarchii adresářů, dokud nenajde soubor pyvenv.cfg v nadřazeném adresáři.
  • Parsuje ho jako INI‑podobný textový soubor — bez externích závislostí, pouze standardním parserem CPythonu.
  • Pokud je include-system-site-packages = false, globální cesty jsou vyloučeny z sys.path před načtením jakéhokoli uživatelského kódu.
  • Formuje nový sys.path: nejprve aktuální skript, potom lib/pythonX.Y, pak lokální site-packages a teprve potom — při explicitním povolení — globální balíčky.

To znamená, že izolace je zaručena i při přímém volání .venv/bin/python -c "import sys; print(sys.path)" bez aktivace shellu. Aktivace (source .venv/bin/activate) ovlivňuje pouze $PATH a VIRTUAL_ENV, ale ne chování interpretátora.

Implementace minimálního venv: co je opravdu nezbytné

Vytvoření funkčního virtuálního prostředí vyžaduje tři komponenty — a nic víc. Ani pip, ani setuptools, ani shell se nepodílí na základní izolaci.

Google AdInline article slot
  • Struktura adresářů: bin/, lib/pythonX.Y/site-packages/
  • Soubor pyvenv.cfg: obsahuje home, include-system-site-packages, version, executable
  • Spustitelný soubor v bin/: symlink (Unix) nebo launcher (Windows), který odkazuje na systémový python

Vše ostatní jsou jen pohodlnosti: pip, activate, pyproject.toml. Zde je minimální pracovní příklad pro Linux:

#!/bin/bash
ENV_DIR="my_venv"
mkdir -p "$ENV_DIR/bin" "$ENV_DIR/lib/python$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')/site-packages"

cat > "$ENV_DIR/pyvenv.cfg" <<EOF
home = $(dirname $(which python))
include-system-site-packages = false
version = $(python -c 'import sys; print(".".join(map(str, sys.version_info[:3])))')
executable = $(which python)
EOF

ln -sf "$(which python)" "$ENV_DIR/bin/python"

Spuštění ./my_venv/bin/python -c "import sys; print([p for p in sys.path if 'site-packages' in p])" ukáže pouze lokální cestu — bez jakýchkoli externích nástrojů.

Co je důležité

  • Izolace virtuálního prostředí je stavem CPythonu, nikoli procesu nebo shellu. Aktivuje se při startu interpretátora, ne při aktivaci prostředí.
  • Soubor pyvenv.cfg je jediným povinným artefaktem. Jeho odstranění promění prostředí v obyčejný adresář se symlinkem.
  • sys.path se přeformátuje před spuštěním jakéhokoli Python‑kódu, včetně site.py. Globální balíčky jsou fyzicky nedostupné.
  • Poetry, Pipenv a další správci závislostí jsou nadstavbami nad venv. Nezmění logiku izolace, ale pouze automatizují tvorbu pyvenv.cfg a správu site-packages.
  • Symbolické odkazy jsou bezpečné: CPython je správně dereferencuje a používá skutečný home z pyvenv.cfg, nikoli cestu k symlinku.

Ladění a diagnostika izolace

Když se prostředí chová nečekaně, kontrolujte ne pip list, ale přímo stav interpretátora:

Google AdInline article slot
  • Ujistěte se, že pyvenv.cfg existuje a obsahuje include-system-site-packages = false.
  • Spusťte .venv/bin/python -c "import sys; print(sys.prefix, sys.base_prefix, sys.path)" — porovnejte prefix a base_prefix.
  • Zkontrolujte, že sys.path obsahuje právě jeden site-packages — ten lokální.
  • Vykonáte .venv/bin/python -c "import site; print(site.getsitepackages())" — měl by vrátit seznam s jedním prvkem.

Pokud jsou globální balíčky stále viditelné, znamená to, že pyvenv.cfg chybí, je poškozený nebo je include-system-site-packages nastaven na true. Žádné proměnné prostředí (PYTHONPATH, PYTHONHOME) toto chování nepřepsají — je pevně zakódováno v CPythonu.

— Editorial Team

Advertisement 728x90

Číst dál