Переносимый офлайн-менеджер Python-пакетов

Я написал CLI-утилиту, которая решает сразу несколько задач. Она позволяет создать локальный архив с портативными версиями Python и любыми пакетами из PyPI. А затем — мгновенно разворачивать проекты без единого запроса в интернет. Также утилита работает из коробки, не требуя сложной настройки серверов — то есть ровно то, что нужно хобби-разработчикам, новичкам и небольшим командам. Хочу поделиться ей здесь, так как думаю, что она может быть полезна кому-то ещё кроме меня.

В конце статьи есть gif с демонстрацией приложения.


Содержание


Зачем я это сделал (и почему это полезно прямо сейчас)

Идея родилась из личного опыта. Как разработчик, я часто сталкиваюсь с ситуациями, когда интернет недоступен или работает плохо:

  • Поездка за город, где связь ловится через раз.

  • Работа в коворкинге или кафе с перегруженным Wi-Fi.

  • Необходимость быстро развернуть проект на новой машине, где нет доступа к сети.

  • Просто желание держать под рукой “слепок” окружения для версионности.

Существующие решения для офлайн-работы с Python-пакетами (devpi, bandersnatch) требуют настройки целого сервера. Это как стрелять из пушки по воробьям. Мне нужен был простой инструмент, который работает как обычная CLI-утилита, имеет uv подобный интерфейс и работает полностью оффлайн (с предварительно загруженными ресурсами). Так родился PyOffline2 — «чемоданчик с инструментами» для Python-разработки.

Стоит упомянуть и возможный “страховочный” сценарий. Этот инструмент может пригодиться не только в поездках, но и в случае, если доступ к зарубежным ресурсам (включая PyPI) станет нестабильным или проблематичным. Это не основной сценарий, и я не драматизирую его, но как дополнительный аргумент — почему бы и нет. Ведь люди покупают страховки, хотя не собираются становиться объектами страховых случаев.

Что умеет проект

  • Скачивать Python — портативные сборки с python-build-standalone через getpybs (команда get-python)

  • Создавать виртуальные окружения на целевой машине: init -pv 3.12

  • Скачивать пакеты с PyPI и распределять их по версиям Python: get fastapi uvicorn или get-from requirements.txt

  • Устанавливать пакеты в целевой проект add fastapi uvicorn или add passlib[argon2] (работает с pyproject.toml)

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

  • Удалять пакеты из целевого проекта с очисткой зависимостей-сирот — аналог uv remove, только полностью офлайн. Удаляет то, что больше не используется ни одним другим пакетом

  • Вести структурированный (машиночитаемый) лог о выполненных операциях корневая папка logs команда folder, чтобы открыть корневую папку приложения.


Кому подойдёт

  • Хобби- и соло-разработчики

  • Небольшие команды

  • Все, кто не хочет поднимать промышленные серверные решения ради сохранения набора любимых библиотек


Как это устроено

Весь проект строится вокруг простой идеи: есть Архив (папка resources), который вы один раз наполняете, и есть ваши Проекты, которые используют этот архив.

Архив (resources/) — это ваше главное хранилище. В нём лежат:

python_storage/ — портативные версии Python (например, 3.10, 3.12), скачанные командой pyoff get-python. Они не требуют установки в систему.

packages_storage/ — пакеты из PyPI (например, fastapi, requests), распределённые по версиям Python. Загружаются командой pyoff get сразу для всех версий, которые есть в python_storage/.

Проект — это ваша рабочая папка с кодом. Когда вы создаёте новый проект (pyoff init -pv 3.12), утилита:

Берёт портативный Python из Архива. Создаёт на его базе виртуальное окружение (.venv) в вашем проекте. При добавлении пакетов (pyoff add fastapi) копирует их из packages_storage. В итоге, вы получаете полностью изолированное окружение, которое работает без единого запроса в интернет.

Схема ниже наглядно это показывает:

схема архива
схема архива

Быстрый старт

Скачать Релиз для своей ОС (win/linux), прописать папку с бинарником в PATH переменных. Затем:

windows:

# базовый кейс (после того как приложение было прописано в системных переменных):
pyoff get-python 3.10 # скачать портативный python в архив (один раз)
pyoff get  fastapi, pydantic # скачать пакеты в архив (для всех python доступных в архиве)
mkdir my-project # создать папку проекта если её ещё нет
cd my-project # перейти в папку целевого проекта (здесь для примера такой путь, у вас своя папка)
pyoff init -pv 3.12 # инициализировать проект создав виртуальное окружение
.venv\Scripts\activate # войти в виртуальное окружение проекта (не обязательно)
pyoff project # посмотреть информацию о проекте
pyoff add fastapi, pydantic # установить пакеты в проект (были скачаны заранее через pyoff get)
pyoff project # посмотреть информацию о проекте
pip list # проверка что пакеты реально установились
pyoff remove fastapi # Удаление fastapi с очисткой "сирот"
pyoff project # посмотреть информацию о проекте
pip list # проверка что fastapi удалился корректно, но pydantic не пострадал

linux:

# базовый кейс (после того как приложение было прописано в системных переменных):
pyoff get-python 3.10 # скачать портативный python в архив (один раз)
pyoff get  fastapi, pydantic # скачать пакеты в архив (для всех python доступных в архиве)
mkdir my-project # создать папку проекта если её ещё нет
cd my-project # перейти в папку целевого проекта (здесь для примера такой путь, у вас своя папка)
pyoff init -pv 3.12 # инициализировать проект создав виртуальное окружение
source .venv/bin/activate # войти в виртуальное окружение проекта (не обязательно)
pyoff project # посмотреть информацию о проекте
pyoff add fastapi, pydantic # установить пакеты в проект (были скачаны заранее через pyoff get)
pyoff project # посмотреть информацию о проекте
pip list # проверка что пакеты реально установились
pyoff remove fastapi # Удаление fastapi с очисткой "сирот"
pyoff project # посмотреть информацию о проекте
pip list # проверка что fastapi удалился корректно, но pydantic не пострадал

Где хранить архив

Единственное, что вам нужно решить — где будет лежать папка с приложением (вместе с архивом resources/). Это может быть:

  • Внешний SSD или флешка (берите с собой в поездки)

  • Общая сетевая папка в офисе (для всей команды)

  • Облачный диск (всё равно не понадобится интернет для установки, только для пополнения)

Никаких настроек серверов, баз данных и Docker-контейнеров. Всего лишь прописать папку с приложением в path переменных.


Итоги

PyOffline2 — это простой, прозрачный и бесплатный open-source инструмент. Он не заменяет uv или pip, а дополняет их. Код открыт, лицензия MIT. Буду рад вашим звездочкам на GitHub, пул-реквестам и любой обратной связи. Ссылки:

❕ Дополнительно

Работа приложения на windows:

windows_instruction
windows_instruction

Работа приложения на linux:

linux_instruction
linux_instruction

Комментарии (2)


  1. orki
    25.06.2026 09:39

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