2025, Nov 15 03:04
Ошибка ImportError в Beanie при PyMongo 4.9 и AsyncMongoClient: причины и решения
PyMongo 4.9 ломает импорт Beanie с ImportError из-за удаления _QUERY_OPTIONS. Объясняем причину и даем 2 решения при переходе с motor на AsyncMongoClient.
При переходе с motor на AsyncMongoClient из PyMongo в проектах, где параллельно используется Beanie или другие ODM, может внезапно всплыть ошибка при импорте. Характерный признак — обычный импорт класса Document из Beanie начинает падать с ImportError сразу после обновления PyMongo. Такое происходит и на актуальных версиях Python: например, описанный ниже кейс воспроизводился на Python 3.11.9 с набором зависимостей beanie==1.29.0 и pymongo==4.13.2.
Как воспроизвести проблему
Сбой происходит на этапе импорта. Минимальный пример выглядит так:
from pymongo.asyncio import AsyncMongoClient as AsyncClient
from beanie import Document as DocBase
Выполнение этого кода приводит к следующей ошибке:
ImportError: cannot import name '_QUERY_OPTIONS' from 'pymongo.cursor'
Что происходит под капотом
Корневая причина — ломащее изменение, внесённое в релизах PyMongo, начиная с 4.9. В этих версиях из pymongo.cursor удалили атрибут _QUERY_OPTIONS. Любая библиотека, которая всё ещё ссылается на этот внутренний атрибут, будет падать при импорте до тех пор, пока не будет обновлена с учётом изменения. Это затрагивает старые версии библиотек в экосистеме MongoDB для Python, зависящих от внутренних деталей PyMongo, включая некоторые сочетания beanie и mongoengine. Это поведение соответствует публичному обсуждению совместимости Beanie, отражённому в соответствующем pull request: https://github.com/BeanieODM/beanie/pull/1027.
Как исправить
Есть два варианта, выбор зависит от ограничений вашего стека. Первый — обновить зависимую библиотеку до версии, совместимой с PyMongo ≥ 4.9. Второй — зафиксировать PyMongo ниже 4.9, чтобы обойти ломащее изменение. Если выбираете фиксацию версий, скорректируйте установку или requirements следующим образом:
pymongo<4.9
beanie==1.29.0
С совместимыми версиями те же импорты будут работать как ожидается:
from pymongo.asyncio import AsyncMongoClient as AsyncClient
from beanie import Document as DocBase
Если вы всё равно планируете более крупный рефакторинг, можно и упростить стек, оставив один только PyMongo. Одна команда отказалась от Beanie и перешла на AsyncMongoClient, отметив, что PyMongo предоставляет полноценную асинхронную поддержку.
Почему это важно
Сбои на этапе импорта особенно болезненны: они блокируют запуск приложения и CI‑конвейеры ещё до выполнения основной логики. Здесь несовместимость вызвана тем, что во внутренностях PyMongo удалили атрибут, а зависящая библиотека продолжала его ожидать. Исправление не в коде вашего приложения, а в выравнивании зависимостей. Важно убедиться, что Beanie или любой другой ODM совместим с выбранным релизом PyMongo — особенно при миграции с motor на AsyncMongoClient.
Выводы
Если после обновления вы видите ImportError: cannot import name '_QUERY_OPTIONS' from 'pymongo.cursor', скорее всего, дело в изменениях PyMongo ≥ 4.9. Решение — обновить зависимую библиотеку до совместимого релиза или зафиксировать PyMongo на версии ниже 4.9. Тем, кто упрощает технологический стек, можно полностью перейти на AsyncMongoClient из PyMongo — он обеспечивает полноценную асинхронность. Ключевой вывод: согласуйте версии ODM и драйвера, чтобы они совпадали в ожиданиях относительно внутренних API.