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.
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.cfgv 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 zsys.pathpřed načtením jakéhokoli uživatelského kódu. - Formuje nový
sys.path: nejprve aktuální skript, potomlib/pythonX.Y, pak lokálnísite-packagesa 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.
- Struktura adresářů:
bin/,lib/pythonX.Y/site-packages/ - Soubor
pyvenv.cfg: obsahujehome,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.cfgje jediným povinným artefaktem. Jeho odstranění promění prostředí v obyčejný adresář se symlinkem. sys.pathse 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í tvorbupyvenv.cfga správusite-packages. - Symbolické odkazy jsou bezpečné: CPython je správně dereferencuje a používá skutečný
homezpyvenv.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:
- Ujistěte se, že
pyvenv.cfgexistuje a obsahujeinclude-system-site-packages = false. - Spusťte
.venv/bin/python -c "import sys; print(sys.prefix, sys.base_prefix, sys.path)"— porovnejteprefixabase_prefix. - Zkontrolujte, že
sys.pathobsahuje právě jedensite-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
Zatím žádné komentáře.