Ошибка установки requirements.txt: причины и решение

Python-приложение падает на сборке, а в панели — стена текста, в которой где-то посередине спрятано «ERROR: Could not find a version…». Руки тянутся искать проблему на стороне хостинга, но почти всегда виноват сам файл requirements.txt. Рассказываем, как за пару минут найти виновника и починить зависимости.

Что видно в логе сборки

Ошибка установки зависимостей выглядит одинаково тревожно на любом хостинге. Первый признак — сборка остановилась, и вместо успешного статуса вы видите красный. В логе характерные кадры:

ERROR: Could not find a version that satisfies the requirement pandas==2.0.0
ERROR: No matching distribution found for pandas==2.0.0

Другой частый кадр — падение не на поиске пакета, а на его сборке из исходников, потому что не хватило компилятора или системных библиотек:

error: command 'gcc' failed with exit status 1
error: Microsoft Visual C++ 14.0 or greater is required

Хостинг здесь ни при чём. Установщик честно делает то, что написано в файле. Если строка битая — он останавливается, и сборка не идёт дальше.

Пять причин, по которым install падает

Несовместимые версии. Пин вида pandas==2.0.0 требует ровно эту версию. Если для Python, который используется на сборке, её не выпускали — установщик её не найдёт. Так же работает конфликт: две библиотеки требуют разных версий третьей, удовлетворить обе нельзя.

Нет системных пакетов. Часть библиотек (psycopg2, lxml, всё, что собирается из исходников) требует компилятора gcc и dev-пакетов вроде libpq-dev. В чистом контейнере их нет, и установка обрывается на сборке wheel'а.

Приватные зависимости. Пакет из внутреннего индекса или с локального пути на сервере сборки не существует. Особенно часто это строки с @ file:///.

Опечатки в названиях. reqeusts вместо requests, лишний дефис, кириллическая буква внутри имени. Установщик не догадается — он просто не найдёт пакет.

Жёсткие пины ==. Файл, целиком слитый через pip freeze, тащит десятки точных версий. Каждый пин — потенциальная точка отказа.

Как читать лог сборки

Не читайте лог целиком, это сотни строк. Ищите ключевые слова и смотрите на последние строки перед остановкой:

  • ERROR и error: — с них начинается причина;
  • Could not find a version — проблема с версией или именем пакета;
  • No matching distribution — пакета нет для этой платформы или версии Python;
  • gcc или exit status 1 — не хватает системных библиотек.

В Dockbox лог сборки льётся в панель проекта в реальном времени, скачивать ничего не нужно — просто откройте проект. Имя пакета из строки ошибки и есть ваш диагноз.

Шаг 1. Уберите несуществующие пины

Найдите в ошибке имя пакета и его строку в файле. Дальше — один из двух приёмов.

Снять пин. Уберите версию, оставьте только имя:

pandas

Выбрать существующую версию. Рядом с ошибкой установщик обычно печатает список доступных версий — возьмите любую оттуда:

pandas==2.2.2

Правило простое: пинить стоит одну-две библиотеки, где версия действительно критична. Всё остальное — без пина.

Шаг 2. Системные пакеты — через Dockerfile

Если ошибка упоминает gcc или exit status 1, установщику не хватает системных библиотек. Сначала попробуйте снять пин: свежие версии популярных библиотек выходят готовыми Linux-wheel'ами, и компиляция не нужна.

Если нужна именно эта версия — добавьте в проект свой Dockerfile: платформа возьмёт его вместо автоматической сборки.

FROM python:3.12-slim
RUN apt-get update && apt-get install -y gcc libpq-dev
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "main.py"]

Свой Dockerfile — не обязательное условие для деплоя, а запасной путь для сложных случаев.

Шаг 3. Приватные зависимости и опечатки

Строки, ведущие на ваш компьютер, удаляют без сожаления:

requests @ file:///Users/alex/projects/app/requests

Оставляйте только имя пакета, а лучше вычеркните строку, если библиотека вам не нужна. Для пакета из внутреннего индекса нужен доступ к нему извне: либо выкладывайте его в публичный индекс, либо переходите на публичный аналог.

Опечатки ловятся вручную: откройте файл и сверьте каждое имя с тем, что реально импортируется в коде. Кириллица внутри имени пакета невидима глазом, но ломает установку мгновенно.

Профилактика

Собирайте файл из импортов, а не из freeze. Пройдите по исходникам и выпишите, что реально импортируется, — flask, requests, aiogram. Пять строк ставятся быстрее и ломаются реже, чем двести.

Держите виртуальное окружение при разработке. Чистое окружение не даст лишним пакетам просочиться в файл:

python -m venv .venv
source .venv/bin/activate
pip install flask requests
pip freeze > requirements.txt

Прогоняйте сборку до пуша. Если локально всё ставится с нуля в чистом окружении — большая часть сюрпризов всплывёт до деплоя.

Не везите папку виртуального окружения. Зависимости ставятся на сборке, .venv в архиве только мешает.

Сколько это стоит

Starter — 990 ₽/мес. 1 vCPU, 2 GB RAM, 20 GB SSD, один проект. Первый месяц бесплатный. Контейнеры работают постоянно, без ограничения по часам и без «засыпания», а тариф действует месяц — сам ничего не списывает.

Pro — 2 490 ₽/мес. 2 vCPU, 4 GB RAM, до пяти проектов.

Team — 4 990 ₽/мес — для команд, которым нужен запас ресурсов и SLA.

Тарифы и детали — на dockbox.host.

Частые вопросы

Что означает «Could not find a version that satisfies the requirement»?

Установщик сходил в индекс пакетов и не нашёл версию под вашу строку. Чаще всего пин не существует для используемой при сборке версии Python, либо в имени пакета опечатка. Рядом установщик печатает список существующих версий — возьмите версию оттуда или снимите пин.

Почему локально всё ставится, а на деплое падает?

На вашей машине многие библиотеки уже стоят с прошлых проектов, поэтому установщик их пропускает. Сервер сборки начинает с чистого окружения и ставит ровно то, что перечислено в файле, — одна плохая строка останавливает всё. Версия Python и операционная система тоже могут отличаться от ваших.

Нужно ли пинить версии в requirements.txt?

Пинить полезно для долгого проекта с воспроизводимыми сборками. Но файл, целиком слитый из pip freeze, создаёт больше проблем, чем решает. Рабочий компромисс — точная версия у одной-двух важных библиотек, остальные без пина.

Что делать, если пакет требует компиляции и системных библиотек?

Сначала снимите пин: свежие версии популярных библиотек обычно идут готовыми Linux-wheel'ами, и компилировать ничего не нужно. Если системные библиотеки правда нужны — добавьте Dockerfile, который их ставит, и платформа возьмёт его вместо автоматической сборки.

Сборка упала — работающий проект остановился?

Нет. Пока новая версия не соберётся успешно, предыдущая продолжает работать и ссылка отвечает как раньше. Панель покажет, что публикация не прошла и почему, а исправленную версию можно загружать сколько угодно раз.