Python venv: полное руководство по виртуальным окружениям

Команда python -m venv .venv — пожалуй, самая копируемая строка в мире Python-разработки. И всё же половина проблем с ModuleNotFoundError, ImportError и внезапно сломавшимся pip начинается с того, что окружение либо не создали, либо активировали не там, либо перепутали интерпретаторы в IDE. Если ставить пакеты глобально в системный Python, рано или поздно один проект потребует Django 4.2, другой — 5.0, а третий потянет несовместимую версию numpy. Виртуальное окружение решает это грубо и надёжно: у каждого проекта появляется своя папка с собственным site-packages, своим pip и своими версиями библиотек.
Особенно болезненна ситуация в Linux и macOS, где системный интерпретатор часто используется самой ОС: от него зависят утилиты, драйверы, менеджеры пакетов дистрибутива. Стоит выполнить sudo pip install в системный каталог — и вы рискуете затереть версию библиотеки, на которую опирается apt или dnf. На Windows такой катастрофы не случится, но конфликт между проектами остаётся: pip держит одну-единственную версию пакета на всю систему. Виртуальное окружение — это каталог с собственным набором установленных пакетов и своим файлом конфигурации. Активировали — команды python и pip указывают внутрь этого каталога. Деактивировали — вернулись к системному интерпретатору.
Модуль venv вошёл в стандартную библиотеку с Python 3.3 по инициативе PEP 405. Он не копирует весь интерпретатор целиком: в каталоге bin (Scripts на Windows) лежат символические ссылки на бинарник Python, а рядом — скрипты activate и pip. Внутри структура выглядит так: bin/ с символической ссылкой на python, include/, lib/python3.12/site-packages/ — сюда ставятся пакеты — и файл pyvenv.cfg с версией интерпретатора и флагами сборки. Именно pyvenv.cfg и особый маркер sys.prefix заставляют интерпретатор считать себя «домашним» и искать модули в локальном site-packages, а не в системном. Если удалить pyvenv.cfg, окружение перестанет быть окружением — Python снова начнёт смотреть наружу.
Базовый сценарий создания одинаков для всех платформ, различаются только пути к скриптам активации. В Linux и macOS это python3 -m venv .venv и source .venv/bin/activate. В Windows через cmd — py -3 -m venv .venv и .venvScriptsactivate.bat, через PowerShell — тот же вызов создания и .venvScriptsActivate.ps1 для активации. Проверить, что всё сработало, помогают команды which python (или where python в Windows) и pip list.
Есть флаги, о которых многие не знают, а они экономят время. --upgrade-deps сразу обновляет pip и setuptools внутри окружения, избавляя от предупреждения при первой установке. --prompt «myproject» меняет префикс в приглашении командной строки — удобно при работе с несколькими окружениями. --system-site-packages разрешает видеть системные пакеты, но это опасный флаг: он частично ломает изоляцию. --without-pip создаёт окружение без pip, если вы ставите зависимости через poetry или uv.
Отдельное правило, которое стоит выучить наизусть: никогда не создавайте venv командой sudo python3 -m venv. Файлы внутри получат владельца root, и потом pip будет падать с ошибкой доступа при каждой установке.
venv — не единственный вариант, и выбор зависит от масштаба проекта. Сравнение основных инструментов выглядит так:
- venv — в стандартной библиотеке с Python 3.3, умеет только установку пакетов с ручным контролем версий через requirements.txt, создаётся за 1–3 секунды.
- virtualenv — не в стандартной библиотеке, работает быстрее за счёт кеширования шаблонов, тоже опирается на requirements.txt, создаётся за 0.5–1 секунду.
- pipenv — строит дерево зависимостей и lock-файл, конфигурация в Pipfile, создаётся несколько секунд.
- Poetry — разрешает конфликты и умеет публиковать пакеты, конфигурация в pyproject.toml, создаётся несколько секунд.
- conda — работает с бинарными пакетами и не только с Python, конфигурация в environment.yml, создаётся десятки секунд.
Для учебных задач и небольших проектов venv закрывает 95% потребностей. Poetry и conda выигрывают там, где нужны научные библиотеки с бинарными зависимостями или строгая фиксация всего дерева пакетов.
Само окружение в репозиторий не кладут — оно привязано к конкретной версии Python и путям на вашей машине. Вместо папки .venv в git попадает список пакетов. Сохранить текущий набор с точными версиями помогает pip freeze > requirements.txt. Развернуть окружение на другой машине — создать venv, активировать и выполнить pip install -r requirements.txt. Выйти из окружения — команда deactivate. У pip freeze есть неприятная особенность: в файл попадают транзитивные зависимости, которые вы не ставили напрямую. Для крупных проектов удобнее держать два файла — requirements.in с прямыми зависимостями и собранный pip-tools requirements.txt с полным деревом и хешами.
Типичные ошибки, которые ловят даже опытных разработчиков, сводятся к нескольким сценариям. Активировали одно окружение, а пакет поставили в другое — проверяйте путь через which python и pip -V: путь к pip должен указывать внутрь .venv. Закоммитили папку .venv — добавьте её в .gitignore одной строкой, иначе репозиторий раздуется на десятки мегабайт. Перенесли окружение в другую папку — абсолютные пути в скриптах активации после этого ломаются, окружение придётся пересоздать. Забыли активировать окружение в IDE — в VS Code и PyCharm интерпретатор выбирается отдельно от терминала. Обновили Python в системе — старые окружения ссылаются на исчезнувший бинарник и перестают запускаться.
Перелом в отношении к виртуальным окружениям у многих наступает, когда два проекта на одной машине требуют разные мажорные версии одной и той же библиотеки для работы с API. Полдня уходит на «магические» ошибки импорта, пока не становится очевидно: причина не в коде, а в единственном глобальном site-packages. С тех пор команда создания venv — первое, что вводят после клонирования любого репозитория, ещё до открытия файла README.
Осталось несколько частых вопросов. Нужен ли virtualenv, если есть venv? В большинстве случаев нет — virtualenv остаётся актуален для Python 2 и для сценариев, где важна скорость создания окружений в CI. Как удалить окружение? Просто удалите каталог .venv целиком, никаких следов в системе не останется.














