2025, Oct 18 04:16

Как установить pyarrow в AWS Lambda: обход ограничений glibc и numpy

Почему pyarrow в AWS Lambda с Python 3.11 падает из-за glibc и numpy, и как это исправить: фиксация версий, переход на Python 3.12 или сборка своего колеса.

Установка pyarrow в базовый образ AWS Lambda кажется простой — пока цепочка зависимостей не упирается в ограничения на уровне системы. Типичный случай: фиксируем numpy ниже 2.3.0 в образе Lambda с Python 3.11, затем добавляем pyarrow — и pip всё равно пытается скачать numpy 2.3.2, после чего сборка падает. Суть проблемы не только в Python‑зависимостях — дело в версии glibc внутри контейнера и отсутствии компилятора.

Минимальный пример

Ниже приведён сценарий, воспроизводящий проблему в образе AWS Lambda с Python 3.11. Сначала ставим ограниченную версию numpy, затем добавляем pyarrow с дополнительным модулем s3.

FROM public.ecr.aws/lambda/python:3.11

RUN python -m pip install "numpy<2.3.0"
RUN python -m pip install "pyarrow[s3]"

Pip продолжает примерно так:

Collecting numpy>=1.25
  Downloading numpy-2.3.2.tar.gz (20.5 MB)
  ...

Что происходит на самом деле

Путь установки pyarrow в контейнере сводится к сборке из исходников. Это заканчивается ошибкой, потому что в образе нет C‑компилятора. Причина, по которой вообще запускается сборка из исходников, — уровень glibc в базовом образе. Образ AWS Lambda с Python 3.11 использует glibc 2.26. Предсобранные колёса для pyarrow 21.0.0 требуют как минимум glibc 2.28, поэтому pip не может взять готовый wheel и пытается компилировать.

Даже если numpy зафиксирован ниже 2.3.0, pyarrow декларирует требование numpy>=1.25. В процессе установки pyarrow резолвер может попытаться перейти на более новый numpy, а из‑за отсутствия совместимых колёс для pyarrow под glibc 2.26 происходит откат к сборке из исходников — и всё ломается.

Решения, соответствующие окружению

Если важно сохранить Python 3.11 и базовый образ Lambda, используйте выпуск pyarrow, который ещё поставляет колёса, совместимые со старым glibc. Фиксация pyarrow на версии 20.0.0 позволяет избежать сборки из исходников в этом образе и проходит без проблем.

FROM public.ecr.aws/lambda/python:3.11

RUN python -m pip install "numpy<2.3.0"
RUN python -m pip install "pyarrow[s3]==20.0.0"

Другой путь — выбрать базовый образ с более новой glibc, чтобы можно было использовать свежие колёса pyarrow. Образ AWS Lambda с Python 3.12 использует glibc 2.34 и работает с актуальными релизами pyarrow.

FROM public.ecr.aws/lambda/python:3.12

RUN python -m pip install "numpy<2.3.0"
RUN python -m pip install "pyarrow[s3]==21.0.0"

Если нельзя менять ни версию pyarrow, ни базовый образ Python, остаётся собрать колесо под glibc 2.26: скомпилировать pyarrow из исходников в среде с такой же или более старой glibc, затем скопировать получившееся колесо в образ Lambda и установить его. Официальные рекомендации по сборке pyarrow доступны в документации Apache Arrow по сборке для Linux и macOS.

На практике разрешение зависимостей иногда работает предсказуемее, когда пакеты устанавливаются одновременно. Установка numpy и pyarrow одной командой pip или через requirements.txt с обоими пунктами помогает показать резолверу полный набор ограничений заранее. Это лишь удобство рабочего процесса и не отменяет необходимости подбирать колёса pyarrow под нужную версию glibc.

Почему это важно

Мир Python‑пакетов часто скрывает, что нативные расширения опираются на системные библиотеки. Если glibc старше целевой для готового колеса, pip переключается на сборку из исходников. Без инструментов компиляции в образе такая сборка неизбежно падает. Понимание связки между glibc базового образа, совместимостью колёс и бинарной поставкой pyarrow объясняет, почему одной фиксации numpy недостаточно — корень проблемы в другом.

Выводы

Если вы на образе Lambda с Python 3.11 и вам нужен pyarrow быстро, зафиксируйте pyarrow на 20.0.0. Если можете перейти на Python 3.12, используйте актуальный pyarrow и ставьте его из готовых колёс. Если версии фиксированы по другим причинам, соберите pyarrow под целевую glibc и установите получившееся колесо в контейнер Lambda. Для более чистого разрешения зависимостей ставьте numpy и pyarrow одной командой pip или через requirements.txt — но помните, что решающим остаётся соответствие glibc и колёс.

Статья основана на вопросе на StackOverflow от Flo и ответе от Nick ODell.