компилятор python3 grpc: как обрабатывать абсолютный и относительный импорт в .protos?

#grpc-python #containerd

#grpc-python #containerd

Вопрос:

Я пытаюсь сгенерировать рабочие модули Python из файлов containerd API .proto, которые можно найти здесь: https://github.com/containerd/containerd/tree/master/api .

К сожалению, собственные файлы containerd .proto содержат ссылки, такие как (in api/events/container.proto ):

 import weak "github.com/containerd/containerd/protobuf/plugin/fieldpath.proto";
 

Теперь этот импорт фактически находится в protobuf/plugin/fieldpath.proto , в отличие от ( vendor/ ) github.com/containerd/... . Простой -I ... в этом контексте не работает, поскольку при импорте используется абсолютный путь «github», тогда как соответствующие источники не расположены внутри ветки поставщика.

Простое копирование исходных текстов внутри vendor/github.com/... приведет к ошибкам во время выполнения при попытке использовать сгенерированные модули Python: это связано с тем, что теперь два отдельных экземпляра для одних и тех же элементов протокола пытаются зарегистрироваться в GRPC с тем же именем элемента протокола, но из двух разных модулей Python. Таким образом, среда выполнения GRPC Python выдает ошибку и завершается.

Как я могу правильно решить эту проблему при использовании python3 -m grpc.tools.protoc ... ?

Ответ №1:

После некоторых проб и ошибок я, наконец, нашел рабочее решение, которое работает следующим образом и которое может быть полезно для других, сталкивающихся с API-интерфейсами на основе gRPC, которые являются более сложными, чем многие примеры gRPC.

  1. скопируйте файлы API .proto в структуру каталогов, которая отражает конечный желаемый пакет Python и структуру модуля. Для containerd это означает наличие всего в структуре containerd / directory, избегая github.com / папки и сглаживание (сглаживание импорта приведет к поломке).
  2. исправьте все пути к операторам импорта, которые либо вызывают сглаживание модулей, либо не соответствуют конечной желаемой структуре пакета. Хороший способ сделать это с помощью sed при копировании файлов proto. В моем случае замените «github.com/containerd/containerd /…» с помощью только путей импорта «containerd / …».
  3. в случае, если файлы vendor’ed .proto каким-то образом связаны с инфраструктурой gRPC и где существуют пакеты gRPC PyPI, такие как grpcio и protobuf, поместите их рядом с вашими файлами API .proto, но не добавляйте их в иерархию каталогов API. Убедитесь, что они помещены в структуру каталогов, которая имитирует структуру пакетов уже доступных пакетов PyPI.
  4. используйте протокол через интерпретатор python3 для генерации модулей Python только для ваших файлов API .proto; убедитесь, что дополнительные файлы .proto из grpc и protobuf доступны для включения, но не создавайте для них модули. протокол делает это уже правильно, если вы не добавляете дополнительные файлы .proto в свои файлы API .proto… так что не делайте этого.
  5. убедитесь, что ваши пакеты grpcio и protobuf PyPI являются последними и каким-то образом синхронизированы, избегайте особенно устаревших дистрибутивных пакетов Debian, устанавливайте из PyPI … даже если это мучительно медленный процесс на arm64, потому что для grpcio и grpciotools нет двоичных дисков. Симптомы, когда это не так, включают ошибки времени выполнения из-за отсутствия полей объекта grpc или protobuf.