Learning Platform
Глоссарий Troubleshooting
Урок 14.03 · 22 мин
Средний
venvvirtualenvcondauv venvPYTHONPATHsys.patheditablePEP 405PEP 660site-packagesRun-on-Your-MachinePitfall 47rufflinterformatterAstral

venv / virtualenv / conda / uv venv + PYTHONPATH + editable installs

Без virtual environment всё установленное через pip install идёт в глобальный site-packages system Python. Один project требует pandas==1.5, другой — pandas==2.0. Конфликт. Решение — virtual environment: изолированный Python interpreter + изолированный site-packages, под каждый project отдельно.

В этом уроке:

  1. Зачем virtual environments — изоляция projects, reproducibility.
  2. Tool comparisonvenv (stdlib) / virtualenv (3rd-party) / conda / uv venv.
  3. PYTHONPATH semanticssys.path module search (cross-link M03 урок 05).
  4. pip install -e . editable installs (PEP 660) — modern editable spec.
  5. site-packages directory layout — где живут установленные packages.
  6. Run-on-Your-Machine #2python -m venv .venv + activate + editable demo.
  7. Pitfall 47.venv/ в .gitignore (иначе ~100 MB venv files в repo).

Зачем virtual environments

# Без venv — всё в global site-packages (требует sudo на system Python)
pip install pandas==1.5     # → /usr/lib/python3.12/site-packages/pandas/...

# С venv — изоляция; нет sudo
python -m venv .venv
source .venv/bin/activate
pip install pandas==1.5     # → .venv/lib/python3.12/site-packages/pandas/...

Преимущества:

  1. Изоляция projects — два projects могут иметь разные pandas versions без конфликта.
  2. Reproducibilityrequirements.txt frozen + .venv recreated 1:1 across machines.
  3. Нет sudo — venv пишет в user-owned directory; не трогает system Python.
  4. Easy cleanuprm -rf .venv удаляет всё; system Python не пострадает.
  5. CI/CD friendly — каждый CI run создаёт fresh venv; deterministic.

Mental model: venv — это clone Python interpreter + clean site-packages, под root directory project. Activation — temporary modification PATH env variable: .venv/bin ставится впереди.


Tool comparison

ToolProvenanceКогда выбирать
venvstdlib since 3.3 (PEP 405)Default new projects — всегда доступен, zero install
virtualenv3rd-party (older, pre-3.3 era)Legacy projects + поддержка Python <3.3; чуть быстрее venv
condaAnaconda — non-PyPI ecosystemData science с native binaries (R interop, MKL, CUDA toolkits); heavier
uv venvAstral — Rust-fastSpeed-critical workflows; pairs идеально с uv pip install

venv (stdlib, PEP 405)

python -m venv .venv                  # creates .venv directory
source .venv/bin/activate             # macOS / Linux
.venv\Scripts\activate.bat            # Windows
which python                          # → .venv/bin/python (verifies activation)
deactivate                            # leaves venv

venv не ставит pip отдельно — copies из system Python. Если ваш system Python имеет pip, venv тоже имеет. Опционально python -m venv .venv --copies (вместо symlinks) для full copy interpreter.

virtualenv — older 3rd-party

pip install 'virtualenv>=20'
virtualenv .venv -p python3.12

Зрелый предшественник venv; activate scripts identical; немного быстрее create. Recommend только для legacy projects, где нужен Python <3.3.

conda — Anaconda non-PyPI

conda create -n myenv python=3.12 pandas
conda activate myenv

conda управляет non-Python dependencies (CUDA, MKL, system libraries) — преимущество для ML/scientific workloads. Trade-off: heavier (~500 MB Anaconda install); package resolution медленнее (conda historically); миксование conda install + pip install чревато (но рабочее).

uv venv — Astral Rust-fast

uv venv .venv                          # ~10× faster than python -m venv
source .venv/bin/activate
uv pip install pandas

Drop-in replacement; pairs с uv pip install natively. Recommend для speed-critical workflows + новых projects.

Cite docs.python.org/3/library/venv.html.


PYTHONPATH + sys.path semantics

Когда вы import foo, Python ищет foo в sys.path — порядок поиска:

import sys
print(sys.path)
# ['',                                     # 1. Скрипт directory (или '' для interactive)
#  '/path/to/PYTHONPATH/dir',              # 2. PYTHONPATH env var dirs (если установлен)
#  '/usr/lib/python3.12',                  # 3. Standard library
#  '/usr/lib/python3.12/lib-dynload',      # 4. C-extension libs
#  '/path/to/.venv/lib/python3.12/site-packages']  # 5. site-packages (vendored / pip installed)

Cross-link M03 урок 05 (modules + imports): мы там разобрали sys.path — Python finder iterates список и берёт первый match. PYTHONPATH расширяет этот список — добавляет ваши custom directories.

# Без PYTHONPATH:
python -c "from mylib import x"            # ImportError

# С PYTHONPATH:
PYTHONPATH=/path/to/mylib python -c "from mylib import x"   # ok

# Альтернатива — pip install -e . (см. ниже) — добавляет project в site-packages

Activation venv добавляет .venv/lib/python3.12/site-packages в sys.path неявно (через pyvenv.cfg + activation script env vars). Это главный механизм изоляции — global system site-packages отсутствует в sys.path после activation.

source .venv/bin/activate
python -c "import sys; print('\n'.join(sys.path))"
# /path/to/project
# /path/to/.venv/lib/python3.12/site-packages
# (НЕТ /usr/lib/python3.12/site-packages — изолировано)

pip install -e . editable installs (PEP 660)

Editable install — special install mode для development. Stages a project в site-packages по reference (через .pth file или modern __editable__ hooks); changes к source видны immediately без reinstall.

cd myproject/                 # имеет pyproject.toml
pip install -e .              # editable install

После этого:

# Edit src/myproject/foo.py
def hello():
    return "world"

# В Python REPL:
from myproject.foo import hello
hello()       # "world"

# Теперь меняем src/myproject/foo.py:
def hello():
    return "edited"

# Re-import (или перезапустить REPL):
from importlib import reload
import myproject.foo
reload(myproject.foo)
myproject.foo.hello()    # "edited" — БЕЗ pip install

До PEP 660 editable installs работали только через setuptools.developpython setup.py develop (legacy). PEP 660 (2021) определил standard PEP 517 entry-point build_editable — теперь любой PEP 517 backend может реализовать editable installs (hatchling, poetry-core, pdm, flit-core все поддерживают).

Use cases:

  • Library development — изменяешь source, тестируешь в REPL без pip install каждый раз.
  • Monorepo — несколько packages, каждый editable-installed — изменения propagate автоматически.
  • CI testing localpip install -e .[dev] ставит project + dev-deps; testing reflects текущий state.

Cite peps.python.org/pep-0660.


site-packages directory layout

После pip install httpx pydantic:

.venv/
├── bin/
│   ├── python -> /usr/bin/python3.12       # symlink к system Python
│   ├── pip                                  # venv-local pip
│   └── activate                             # source-able shell script
├── include/
│   └── python3.12/                          # для C-extension headers
├── lib/
│   └── python3.12/
│       └── site-packages/                   # ← всё установленное живёт здесь
│           ├── httpx/
│           │   ├── __init__.py
│           │   └── _client.py
│           ├── httpx-0.25.2.dist-info/      # metadata (version, deps, RECORD)
│           ├── pydantic/
│           ├── pydantic-2.5.0.dist-info/
│           └── _virtualenv.py
└── pyvenv.cfg                               # venv config (Python version, base prefix)

Windows variant: .venv\Scripts\python.exe + .venv\Lib\site-packages\.

.dist-info directory содержит METADATA (PEP 621 metadata уровень), RECORD (file manifest + hashes), WHEEL (build metadata) — это install artifact от вашего wheel/sdist.


Run-on-Your-Machine #2 — venv create + activation + editable

Шаг 1. Создайте virtual environment в текущем directory:

python -m venv .venv
ls .venv/
# bin/  include/  lib/  pyvenv.cfg

Шаг 2. Активируйте + verify:

source .venv/bin/activate              # macOS / Linux
# .venv\Scripts\activate.bat           # Windows alternative

which python                           # → /your/path/.venv/bin/python
python -c "import sys; print(sys.prefix)"   # → /your/path/.venv (vs /usr)

Шаг 3. Editable install существующего project (нужен pyproject.toml с [project] table — см. урок 01):

# Минимальный pyproject.toml (cd в project root):
# [build-system]
# requires = ["hatchling"]
# build-backend = "hatchling.build"
# [project]
# name = "demo"
# version = "0.1.0"
# requires-python = ">=3.11"

pip install -e .
# Successfully installed demo-0.1.0

Шаг 4. Cleanup:

deactivate
rm -rf .venv

Pitfall 47: добавьте .venv/ в .gitignore сразу при создании. venv ~100 MB (зависит от установленных deps); commit’ить в git — это disaster для repo size + lock-file conflicts. Standard .gitignore template:

.venv/
__pycache__/
*.egg-info/
dist/
build/
.pytest_cache/

Что нельзя в browser? Pyodide WASM не имеет subprocess access — python -m venv .venv требует filesystem write + spawning subprocess; невозможно. Поэтому venv mechanics — host-only.


Run-on-Your-Machine — ruff linter + formatter

После создания venv типичный workflow — установить tooling для качества кода. С 2024+ дефакто-стандарт — ruff (Astral, Rust) — single tool который заменяет связку flake8 + pylint + pycodestyle + pyflakes + pyupgrade + isort + black. Производительность — 10–100× быстрее Python-equivalents (реальные replays — на средних codebase с 10K LOC ruff завершает full lint за <1 сек, vs 30+ сек для pylint/flake8 chain).

# Установка через pip (внутри активированного venv) или uv tool (global isolated)
pip install 'ruff>=0.6'
# или
uv tool install ruff           # standalone binary в ~/.local/share/uv/tools/

ruff --version                 # → ruff 0.6.x

Two main commands:

# Linting — finds bugs, anti-patterns, style issues
ruff check src/                # lint все .py в src/
ruff check --fix src/          # auto-fix для safe rules (e.g., unused imports)

# Formatting — replaces black; PEP 8 + opinionated formatting
ruff format src/               # форматирует in-place
ruff format --check src/       # check-only (CI mode — exit 1 если нужны изменения)

Конфигурация в pyproject.toml (single source of truth — рядом с [project] table из урока 01):

[tool.ruff]
line-length = 100
target-version = "py312"

[tool.ruff.lint]
# Включить набор правил (E + W — pycodestyle, F — pyflakes, I — isort, UP — pyupgrade, B — bugbear, SIM — simplify)
select = ["E", "W", "F", "I", "UP", "B", "SIM"]
ignore = ["E501"]              # line too long — handled formatter'ом

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
docstring-code-format = true   # форматировать code blocks в docstrings

Что заменяет ruff:

ToolЗаменено в ruffNotes
flake8YES (rules E, W, F)Полный pycodestyle + pyflakes coverage
pylintЧастично (rules PL*)~70% coverage — некоторые advanced semantic checks остаются за pylint
pycodestyleYES (rules E, W)PEP 8 violations
pyflakesYES (rules F)Unused imports, undefined names
pyupgradeYES (rules UP)Modernize syntax (f-strings vs .format(), list[int] vs List[int])
isortYES (rule I)Import sorting + grouping
blackYES (ruff format)Drop-in replacement; 99% совпадение с black output
banditЧастично (rules S*)Security checks

Performance — Rust binary + parallel execution + AST cache:

# На pandas codebase (~1500 .py files, ~200K LOC):
time pylint pandas/             # ~120 секунд
time flake8 pandas/             # ~25 секунд
time ruff check pandas/         # ~0.4 секунды

100–300× speedup на больших codebase — это ощутимая разница в CI run time + developer feedback loop.

CI integration (рядом с pytest из M08):

# В CI script:
ruff check --output-format=github src/    # GitHub Actions annotations
ruff format --check src/                  # exit 1 если форматирование некорректно
pytest tests/                             # unit tests из M08

Pitfall: ruff vs black config compatibility. ruff format aims на 99% black-compatible output; differences в edge cases (magic trailing comma, slice formatting). Если переходите с black на ruff format в существующем codebase — first run может произвести diff на ~5–10% files. Solution — single formatting commit baseline, потом ruff format в CI блокирует regressions. Cite Ruff Formatter Differences from Black.

Что нельзя в browser? ruff — native Rust binary; Pyodide WASM не запускает binaries. Linting feedback в challenges ограничен Wave 0 lints (forbidden imports / forbidden functions); full ruff — host-only Run-on-Your-Machine.

Cite docs.astral.sh/ruff + Ruff GitHub.


Cross-course → Spark Airflow orchestration

Airflow tasks running PySpark jobs обычно изолируются venv-per-task для dependency conflicts (один DAG требует pandas 1.5, другой — pandas 2.0). PythonVirtualenvOperator — Airflow-native механизм:

# Airflow DAG:
PythonVirtualenvOperator(
    task_id="ml_inference",
    requirements=["scikit-learn==1.3", "pandas==1.5"],
    python_callable=run_inference,
)

Cross-course: Spark course Phase 12 — production operations — orchestrating Spark jobs from Airflow + Python virtualenv operators + dependency mgmt patterns. Same idea: Python venv mechanics extend в distributed orchestration; per-task venvs нивелируют version conflicts.


Что в следующем уроке

Урок 04 — dependency resolution. Semver concept (MAJOR.MINOR.PATCH); PEP 440 version specifiers (~=, >=, <, ==, !=); lock files (poetry.lock / uv.lock / requirements.txt frozen); PEP 735 [dependency-groups] table (modern dev-deps grouping). Cross-course → Spark cicd-lifecycle + Airflow Python deps mgmt.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. **Apply — venv create:** Какая stdlib команда создаёт virtual environment?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5