PythonMiddleTechnical

Что такое lock-файл и зачем он нужен?

Lock-файл (poetry.lock, uv.lock, requirements.txt от pip-compile) фиксирует точные версии и хеши всех зависимостей, включая транзитивные. Нужен для воспроизводимых сборок, безопасности и стабильного CI. Для приложений lock коммитим в git и ставим в проде с --frozen/--require-hashes; в библиотеках — нет.

Что такое lock-файл

Lock-файл — это файл, в котором зафиксированы точные версии всех зависимостей проекта (включая транзитивные) и часто их хеши. В отличие от pyproject.toml/requirements.in, где обычно стоят диапазоны (fastapi>=0.110), lock закрепляет конкретные сборки (fastapi==0.115.2, starlette==0.38.6, …) ровно те, что были разрешены в момент его генерации.

Зачем он нужен

  • Воспроизводимость: одинаковая среда в dev/CI/prod и через полгода после релиза.
  • Безопасность: хеши в lock защищают от подмены содержимого пакета на PyPI/зеркале.
  • Управление транзитивами: исключает «вчера работало — сегодня сломалось» из-за минорного апдейта чужой зависимости.
  • Аудит: легко прогнать pip-audit/safety по фиксированному списку.

Инструменты в экосистеме Python

  • pip-tools: requirements.inpip-compilerequirements.txt (lock).
  • poetry: pyproject.toml + poetry.lock, команды poetry lock, poetry install --sync.
  • uv: pyproject.toml + uv.lock, команды uv lock, uv sync; очень быстрая нативная реализация резолвера.
  • pipenv: Pipfile + Pipfile.lock (использование падает).
  • pdm: pyproject.toml + pdm.lock, поддержка PEP 582.

Типовой workflow (pip-tools)

# requirements.in
# fastapi>=0.110
# sqlalchemy[asyncio]>=2.0

uv pip install pip-tools
pip-compile --generate-hashes --resolver=backtracking requirements.in
# создаст requirements.txt c пинами и --hash=sha256:...

# В CI/проде:
pip install --require-hashes -r requirements.txt

# Обновление зависимости:
pip-compile --upgrade-package fastapi requirements.in

Пример с uv

uv init
uv add fastapi sqlalchemy httpx
uv lock                    # сгенерирует/обновит uv.lock
uv sync --frozen           # установит ровно то, что в lock (CI/prod)
uv lock --upgrade-package httpx

Application vs library

  • Приложение (сервис, бот, CLI): lock коммитим в git, в проде ставим из lock с --frozen/--require-hashes. Это норма.
  • Библиотека (публикуется на PyPI): в pyproject.toml держим широкие диапазоны, lock не публикуем и не навязываем пользователям. Lock можно держать только для собственного CI, чтобы прогонять тесты в воспроизводимой среде.

Подводные камни

  • Lock привязан к платформе и интерпретатору: lock, собранный под Linux/CPython 3.12, может не подойти для macOS/3.11 (бинарные wheel разные). Решения: универсальные lock (uv поддерживает multi-platform), пересборка lock в CI под целевую ОС.
  • Lock без хешей не защищает от подмены пакета; всегда включайте --generate-hashes для prod-сервисов.
  • Слепое poetry update/uv lock --upgrade ломает прод: обновляйте точечно по пакету и прогоняйте тесты.
  • pip install -r requirements.txt без --require-hashes и без --no-deps/--constraint может подтащить более свежие транзитивы — используйте pip install --require-hashes или pip-sync.
  • Lock в Docker должен копироваться до кода (отдельным COPY pyproject.toml uv.lock ./ + uv sync --frozen), иначе ломается кеширование слоёв.
  • Конфликты при мерже lock — норма. Не правьте файл руками: ресольвьте pyproject.toml/requirements.in, затем перегенерируйте lock.

Common mistakes

  • Говорить, что lock нужен только для скорости.
  • Не упоминать transitive dependencies.
  • Путать constraints file и lock semantics.

What the interviewer is testing

  • Объясняет reproducibility.
  • Понимает direct/transitive versions.
  • Знает workflow обновления lock.

Sources

Related topics