Найти в Дзене

Python + VENV (виртуальное окружение) питона без "синей изоленты"

Оглавление

Одной из "трудных" тем при работе с питоном является его "виртуальное окружение" (VENV), идеологию которого многие не понимают, а потому и боятся использовать.

Мне кажется, что это происходит из-за крайне неудачной формулировки и описания "Что же из себя `ОНО` представляет", поскольку при проникновении "в уши" буквосочетаний "виртуальное окружение" и "изолированная среда выполнения" у русского человека в голове возникает образ человеческой головы с надетыми на нее очками виртуальной реальности ("виртуальное" ведь!), насмерть примотанными к голове синей изолентой, как по вертикали, так и по горизонтали и диагонали шапочка из фольги("изолированное" ведь!), и с пришпандоренным на макушке пулеметом ("окружают" ведь! Но у нас еще веник старый рядом есть, если что - им отбиваться будем). А... еще антенны из ушей торчат...

Примерно такие ассоциации возникают у НОРМАЛЬНОГО русского человека. Он такого "образа" боится, поэтому первая мысль, возникающая в его голове при виде этого образа - "Да ну его на хер!!!".

Но не так уж все страшно, поэтому я предлагаю просто изменить формулировки, принятые в Python, на более близкие русскому менталитету.

Итак:

  • Питон - это "базовая" электронная библиотека Python определенной версии с книгами
  • VENV - филиал "базовой" библиотеки Python, который может содержать:
    - только свои книги
    - все книги из основной библиотеки + свои книги
  • Пакет питона - книга в любой из библиотек, в каждой из которых содержатся инструкция о том, как выполнять какую-то определенную задачу на питоне.
  • PIP - библиотекарь, который работает с книгами, добавляет новые, удаляет ненужные, ведет список и каталог книг, выдает справки о наличии книг и их описание.

Установка "базового" питона

Питон (базовый) мы (обычно) ставим в систему, когда проводим его инсталляцию из дистрибутива, скачанного с https://www.python.org/downloads. Во время установки не включайте питона в PATH, не ставьте всякие "лаунчеры" и т.п.

Не ставьте в PATH!!! Питонов обычно стоит несколько, и они могут начать "путаться"...
Не ставьте в PATH!!! Питонов обычно стоит несколько, и они могут начать "путаться"...
Ставим только PIP, все остальное на хрен не нужно... (если вы не знаете, что такое /tk, и зачем он нужен)
Ставим только PIP, все остальное на хрен не нужно... (если вы не знаете, что такое /tk, и зачем он нужен)
Я ставлю 3.12 версию (для примера) в папку "c:\p312"
Я ставлю 3.12 версию (для примера) в папку "c:\p312"

После того, как инсталляция закончилась, можете перемещать папку "p312" куда угодно, переименовывать ее как угодно и т.п. На работоспособность питона это никак не влияет. Можете архивировать эту папку, пересылать, разархивировать на новом месте и снова запускать, все останется работоспособным, т.к. у питона нет понятия "Портабельный" или "Системный", "привязка питона к месту" отсутствует, "привязка" происходит на уровне самой Windows (лаунчеры, PATH, деинсталляторы и т.п.), это Windows привязывается к месту, куда инсталлировала питон, а не наоборот!

Установка "скачанного" питона

Если есть желание (или необходимо поставить питона дистанционно из BAT-файла), можете просто скопировать себе весь комплект питона нужной версии с уже находящимся в его каталогах стартовым набором всех компонентов, и поместить его в папку с именем, которое вам больше нравится.

Версии питона, не требующие инсталляции, вместе с командами их скачивания и разархивации, находится вот тут: https://github.com/Nestorchik/python/releases

Там находятся просто полные копии питона, "инсталлированного" его стандартным инсталлятором, заархивированного в CAB-формате (расширение PAK), поэтому разархивация этих архивов производится средствами самой Windows.

ВАЖНО: Работоспособность питона не зависит от его месторасположения, т.к. все пути до нужных ему компонентов он отсчитывает от "самого себя" от места запуска файла "python.exe". Это правило относится К ЛЮБОМУ питону, как к "базовому", так и к "VENV" питону!!!

"Базовым" питоном я его назвал потому, что именно ОТ НЕГО создаются ЕГО ФИЛИАЛЫ - (venv), т.к. в каждом "филиале" стоит ссылка на "базу"!

Давайте рассматривать Питон как "директора библиотеки", и, когда нам надо что-то от питона, мы даем команду напрямую "директору библиотеки" - файлу "python.exe", а уж дальше он сам вызывает своих "подчиненных" и выдает команду им самостоятельно. Все, что нам надо знать о "Библиотеке" - это полный "адрес" директора (в нашем случае это "c:\p312\python.exe")

Создание "филиала" (venv)

Считаем, что Питон у нас установлен на "c:\p312", теперь давайте создадим его "Филиал" (venv). В базовом питоне есть "книжка" с названием "venv", в которой "написано" как создавать филиалы, к этой "книжке" питон и обращается, когда требуется "создать филиал", делается это командой:

c:\p312\python -m venv [необязательные ключи] d:\venv_ComfyUI

Разберем команду:

  • c:\p312\python <- обращаемся к "директору"
  • -m <- указание вызвать "модуль"
  • venv <- с названием "venv"
  • [необязательные ключи] <- дополнительные параметры (читай ниже)
  • d:\venv_ComfyUI <- по этому пути и в папке с таким именем создать "филиал"

[Необязательные ключи] могут быть следующими:

  • -h, --help
    справка
  • --system-site-packages
    Включить в "филиале" доступ ко всем "книжкам" базового питона
  • --symlinks
    Использовать символические ссылки вместо копий файлов в "филиале"
  • --copies
    Использовать копии, а не символические ссылки, даже если символические ссылки являются значениями по умолчанию для платформы.
  • --clear
    Удалите "филиал", если такой уже существует, перед его созданием.
  • --upgrade
    Обновить версию питона "филиала" до версии "базового", если "базовый" был обновлен на месте.
  • --without-pip
    Не устанавливать в "филиале" PIP
  • --prompt PROMPT
    Установить свое "приглашение командной строки".
  • --upgrade-deps
    Обновить основные зависимости (pip) до последней версии в PyPI

Но, я бы (лично я!) создавал "филиал" такой командой:

c:\p312\python -m venv --system-site-packages --symlinks d:\venv_ComfyUI
В результате применения ключа "--symlinks", вместо копирования EXE и DLD файлов из "базового" питона в "филиал", в него помещаются "символические ссылки" на них, что еще более экономит место.
Зеленым - сим-линки вместо самих файлов.
Красным: два лишних EXE-шника для PIP можно удалить, они просто дубликаты основного pip.exe для совместимости типа "Вдруг какой дурак так вызовет...". А файлами "activate/deactivate" я не пользуюсь В ПРИНЦИПЕ.
Зеленым - сим-линки вместо самих файлов. Красным: два лишних EXE-шника для PIP можно удалить, они просто дубликаты основного pip.exe для совместимости типа "Вдруг какой дурак так вызовет...". А файлами "activate/deactivate" я не пользуюсь В ПРИНЦИПЕ.
Из предустановленных "книжек" мы имеем только PIP (библиотекаря)
Из предустановленных "книжек" мы имеем только PIP (библиотекаря)
И имеем самый главный файл конфигурации "филиала библиотеки" - "pyenv.cfg"
И имеем самый главный файл конфигурации "филиала библиотеки" - "pyenv.cfg"
В котором находятся все необходимые нам настройки и данные.
В котором находятся все необходимые нам настройки и данные.

Итак, в этом файле:

  • home - где находится "базовый" питон. Если в "филиале" будет чего-то не хватать, филиал будет искать "дома".
  • include-system-site-packages = true - включен доступ ко всем "книгам" базового питона. Для закрытия доступа просто смените на "false" (вдруг пригодится).
  • version - версия питона
  • executable - ссылка на "директора библиотеки"
  • command - команда с помощью которой создавался "филиал".

Итак, мы теперь фактически имеем две "библиотеки", одну "базовую":

c:\p312\python.exe

... и один "филиал":

d:\venv_ComfyUI\Scripts\python.exe

Поскольку в филиале включен доступ ко всем книгам базовой библиотеки, пока для нас они равнозначны.

Если мы установим (к примеру) ComfyUI как:

cd /d d:\
git clone
https://github.com/comfyanonymous/ComfyUI.git
(произойдет установка ComfyUI в папку "d:\ComfyUI" )

... и вызовем установку пакетов ComfyUI командой:

c:\p312\python -m pip install -r d:\ComfyUI\requirements.txt

(не забыть предварительно torch-cuda установить, или пропатчить потом!)

... то можем запускать ComfyUI двумя командами, как:

c:\p312\python d:\ComfyUI\mail.py --auto-launch

... так и командой:

d:\venv_ComfyUI\Scripts\python d:\ComfyUI\mail.py --auto-launch

... что в нашей (этой!) конфигурации совершенно равнозначно. Откуда мы его не запускаем, "книжки" все равно берутся из "базовой" библиотеки.

НО ЭТО ПОКА! Пока мы не положили какие-то "книжки" в библиотеку филиала.

В "филиале" у нас тоже есть свой "библиотекарь" (pip), и теперь мы можем давать указания двум директорам библиотек (а они своим библиотекарям), "базовой" и "филиала". Какие правила выбора книг существуют в этих двух разных "библиотеках"?

Правила выбора "книг" в "библиотеках"

Мы, к примеру, завезли в "базовую библиотеку" книжку "Numpy==2.1.1", а в ее "филиал" книжку "Numpy==2.0.0".

Куда нам надо обращаться за конкретной книгой "Numpy==2.1.1"???

Куда что завезли, туда и обращаемся, с одной лишь разницей, что:

  • если в "филиале" есть нужная книга, она выдается посетителю из "филиала", даже, если точно такая же есть в " базовой" библиотеке.
  • если в "филиале" нужной книги нет, то происходит обращение к "базовой" библиотеке, и, если она там есть, то она выдается как книга "из филиала".

Есть еще несколько правил обращения с "книгами", они такие:

  • если "include-system-site-packages = true", то "филиал" имеет доступ ко всем книгам "базовой", она считает их как "имеющиеся в наличии у себя", если FALSE, то даже не обращается к базовой, ограничиваясь своими "книгами".
  • "базовая" библиотека ни куда не обращается вообще, она даже может не знать, что у нее есть "филиалы", и оперирует только своими книгами.
  • "филиал" имеет полный доступ к своим книгам (удаление, установка, обновление и т.п.), а к книгам "базовой библиотеки" только "на чтение".
  • если "филиалу" идет команда "установить книгу", а такая уже есть в "базовой" библиотеке, она считается уже установленной, и в установке будет отказано.
  • "филиал" физически не может изменить "ассортимент" книг в базовой библиотеке, поскольку имеет доступ к ней "только чтение".

Примерно вот так вот...

Что это дает?

Дает возможность строить систему питона очень гибко, избегать конфликтов версий, когда одному компоненту требуется одна версия какой-то "книги", а другому компоненту другая версия той же книги.

Пример:

c:\p312\python -m venv --system-site-packages --symlinks d:\venv_numpy1.22.0
c:\p312\python -m venv --system-site-packages --symlinks d:\venv_numpy2.0.0
c:\p312\python -m venv --system-site-packages --symlinks d:\venv_numpy2.1.1
c:\p312\python -m pip torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124
c:\p312\python -m pip install -r d:\ComfyUI\requirements.txt
c:\p312\python -m pip uninstall numpy -y
c:\p312\python -m pip install numpy==1.19.0
d:\venv_numpy1.22.0\Scripts\python -m pip install numpy==1.22.0
d:\venv_numpy2.0.0\Scripts\python -m pip install numpy==2.0.0
d:\venv_numpy2.1.1\Scripts\python -m pip install numpy==2.1.1

Что я тут сделал?

Я создал три "филиала" (venv) с разными путями и с "доступом ко всем книгам базового питона".

В "базовый" питон сначала поставил torch+cuda (чтобы потом не удалять того, что сам комфи поставит, а он не того поставит!).

В "базовый" питон установил все "книжки", которые "читает Комфи".

Потом удалил из "базового набора" книжку "Numpy" независимо от версии.

Потом поставил в "басовый питон" книжку "numpy==1.19.0"

Потом поставил версии "1.22.0", "2.0.0" и "2.1.1" каждую в свой "филиал".

Теперь могу запускать Комфи с разными версиями "Numpy" просто меняя путь к файлу "python.exe" в той папке, внутри которой я установил нужную мне сейчас версию "Numpy". Сам интерфейс (Комфи) один и тот же, меняется только питон, а вместе с ним и "книжки", которые в него вложены.

c:\p312\python d:\ComfyUI\mail.py --auto-launch
d:\venv_numpy1.22.0\Scripts\python d:\ComfyUI\mail.py --auto-launch
d:\venv_numpy2.0.0\Scripts\python d:\ComfyUI\mail.py --auto-launch
d:\venv_numpy2.1.1\Scripts\python d:\ComfyUI\mail.py --auto-launch


Именно таким образом и строится иерархическая система VENV питона, когда фактически создается заново только "отличающаяся от стандартного небольшая часть", а "общая часть книг" находится в "базовой" библиотеке, а не прикладывается по полной библиотеке книг к каждому приложению.

P.S.

Советы по работе с VENV:

  • Забудьте на хрен (как ночной бред!), об "активации" и "деактивации" "виртуального окружения питона"!!! Как "Хорошо зафиксированная женщина в предварительных ласках не нуждается", так и "Нормально (с умом!) запущенный питон в активации не нуждается!"
  • Питон в VENV, не требует никакой активации, если команда отдается "директору", а сам "директор" вызывается по полному его пути!!!
  • Все обращения к модулям питона выполняйте через обращение к "директору" с указанием ключа "-m" перед модулем, который хотите вызвать.
    К примеру: "pip" вызывается как "full_path:\\python -m pip", а не просто "pip"!!!
  • Если вам надо "перевести книжки" из одного питона в другой (в пределах одной версии), не юзайте PIP, а просто перекиньте папки с нужными книгами из "Lib\site-packages" одного питона в другой (про установку пакетов без PIP читай тут: https://dzen.ru/a/ZtxI7afHcxO7qtJo)
  • Про организацию совместного использования пакетов питона несколькими приложениями читайте тут: https://dzen.ru/a/Zr5J2oGpiy6Bx86b

Удачи!
NStor
https://t.me/stable_cascade_rus
https://t.me/srigert