Python: Настройка окружения
Теория: Виртуальные окружения
Представим, что мы начинаем работу с несколькими проектами. В каждом проекте могут быть разные наборы зависимостей. Еще более тяжелый случай: разные проекты могут иметь в зависимостях разные версии одной и той же библиотеки.
Чтобы предотвратить возможный конфликт, пакетный менеджер устанавливает зависимости проекта в его собственную директорию зависимостей - .venv. Но это не единственная функция этой директории.
Виртуальное окружение
Заглянем в директорию .venv:
Здесь нам важны две директории: bin и lib. Вторая директория, lib/python3.XX/site-packages вам уже знакома - в ней установлены все зависимости проекта. Тогда как в директории .venv/bin лежит ссылка на интерпретатор Python. Для чего это нужно? Давайте сперва поставим библиотеку в наш проект.
Создадим новый файл module.py, импортируем библиотеку и сделаем пару вызовов:
Запустим наш модуль с кодом:
Почему же мы получили ошибку, ведь мы установили библиотеку в проект? Суть в том, что Python используется в операционной системе для запуска системных утилит. Зависимости этих утилит хранятся в /usr/lib/python3.XX/site-packages - директории общей для всей системы. И Python ищет зависимости в своих, системных директориях.
Но ставить зависимости проекта в системные директории нельзя, будут конфликты. Тогда мы можем поступить наоборот, и запустить Python из директории .venv нашего проекта. Для этого в ней и лежит ссылка на интерпретатор.
Сочетание директории с зависимостями (lib/python3.XX/site-packages) и ссылки на интерпретатор (bin/python3) называется окружением. Окружение системного Python называют глобальным окружением, а окружение проекта локальным или чаще всего виртуальным окружением. Отсюда и название директории .venv - Virtual Enviroment.
Но каждый раз вызывать код указывая полный путь до интерпретатора внутри .venv утомительно. Потому существует механизм подмены пути автоматически - активация окружения. При активации в переменную PATH, подставляется путь до интерпретатора внутри .venv. Затем, когда мы вызовем команду python3, то запустится Python внутри окружения. А когда мы закончим работу в окружении, останется лишь вернуть прежний путь, или еще говорят деактивировать окружение, чтобы система продолжила использовать системный Python с его библиотеками.
В действительности этот процесс приходится выполнять так часто, что пакетные менеджеры его автоматизируют.
Команда uv run <команда> активирует окружение, выполняет команду в нем и деактивирует его. Так вся работа с окружением скрыта от нас. В дальнейшем все команды запуска кода и утилит в проекте мы будем выполнять через uv run.
Управление версиями Python
Разные проекты могут требовать не только разных версий библиотек, но и разных версий Python. При этом обновлять Python, установленный в системе, нельзя - могут сломаться системные утилиты. К счастью, механизм окружений позволяет управлять не только зависимостями, но и интерпретаторами. Вместо ссылки на системный Python можно указать ссылку на другую, отдельно скачанную версию.
uv также автоматизирует этот процесс, по умолчанию uv использует ссылку на системный интерпретатор, но для многих команд можно указать версию Python через флаг --python:
Если указанной версии нет в системе, то uv скачает ее и будет использовать для текущего проекта. Системный Python это никак не затронет, так как интерпретатор проекта полностью изолирован.

