Рубрики
Без рубрики

Итератор, который не был: любовное письмо на BOTO3 Paginators

Объект об ошибке BOTO3 «Объект страницы» не является итератором «казалось, что юмористическая ложь, пока Python Pookbook не помогла поставить ее в перспективу. Помечено Python, BOTO3, AWS.

Этот пост изначально появился на внутреннем блоге компании, а также адаптирован здесь с разрешения.

BOTO3 Является ли Python SDK для AWS. Это делает отличную работу, делая AWS APIS, чувствующ ротон Python. Этот пост – любовное письмо к одной конкретной функции – Paginators Отказ

Ну, это то, что или оправдание, чтобы повеселиться с сообщением об ошибке «Объект страницы не является итератор»

API и пагинация в двух словах

Когда вам нужно получить список объектов из сервиса, большинство API будут вернуть этот список в кусках, если существует большое количество результатов. Это обычно хорошая вещь для всех:

  • API может получить вам одну страницу результатов быстрее, чем может отправить все
  • Вы можете начать работать рано
  • Если вы бросаетесь в середине обработки, есть менее потраченные усилия

Все выигрывают!

BOTO3 и Pagination – DIY Mode

Когда AWS API вернет усеченный ответ, они включают в себя токен, который вы можете использовать для получения следующей страницы результатов.

Если вам нужно создать полный результат, установленный из страничных ответов, один вариант – обрабатывать все самостоятельно. Например, вот один из способов вы можете получить История ценообразования на месте В первый день октября 2019 года:

import boto3
from datetime import datetime

ec2 = boto3.client('ec2')
params = {
    'StartTime': datetime(2019,10,1),
    'EndTime': datetime(2019,10,1)
}

results = []

while params.get('NextToken') != '':
    response = ec2.describe_spot_price_history(**params)
    results.extend(response['SpotPriceHistory'])
    params['NextToken'] = response['NextToken']

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

  • NextToken Возвращается в пагированное отклика, и вы кормите его в последующий запрос, чтобы получить другую страницу результатов
  • SpotPriceSistory где вы смотрите в каждый ответ на данные результата, которые вы заботитесь о

Может быть легко смешать вещи при обращении этих токенов, и сделать вещи более интересными, точные правила Paginator варьируются по службе. См. Отличное резюме IAN MCKAY в IANN0036/AWS-Pagination – правила Чтобы увидеть, насколько разнообразны эти правила.

BOTO3 включает в себя полезные Paginator Абстракция, которая делает весь этот процесс намного более гладкой. Чтобы получить коллекцию объемов EBS, например, вы можете сделать что-то подобное:

client = boto3.client('ec2')
paginator = client.get_paginator('describe_volumes')
vols = (vol for page in paginator.paginate()
        for vol in page['Volumes'])

Абстракция Paginator помогает бумаги над различиями между услугами и скрывает кучу деталей под ковриком Так что вам не нужно заботиться о них.

Мое растерянность

На какой-то момент вскоре после изучения пагинаторов Boto3 я экспериментировал с некоторым кодом и хотел посмотреть только на первую страницу результатов. Видеть это Paginate () Возвращает Pagterterator Я подумал, что смогу сделать что-то вроде этого:

page_iter = paginator.paginate()
first_page = next(page_iter)

Но нет! Я вернул это сообщение об ошибке:

TypeError: PageIterator object is not an iterator

Чего ждать?

Поэтому у меня был объект, который называл себе итератором и отлично работал в цикле. Но это не будет работать с Далее () или индекс (например, Page_iter [0] ). Как обходной путь, я попробовал это:

page_iter = iter(paginator.paginate())
first_page = next(page_iter)

И … это сработало. Я не совсем понял Почему Это сработало или было необходимо в первую очередь. Я только что решил по какой-то странной причине, которую я должен был сделать Явно Что за цикл делал неявно . Это было не то, что мне нужно было сделать все это часто, поэтому я не давал ему слишком много мысли.

Поваренная книга разъясняет

Быстро пересылая немного, я прочитал отличный | Дэвид Безли Python Cookbook Отказ Рецепт 4.6 в 3-м издании называется «Определение генераторных функций с дополнительным состоянием». Кратко описывает, что Boto3’s Pagterterator делает и почему. Рецепт открывается с этим:

Проблема: Вы хотели бы определить функцию генератора, но она включает в себя дополнительное состояние, которое вы хотели бы как-то разоблачить пользователю. (Beazley, Дэвид; Джонс, Брайан К .. Python Cookbook: рецепты для освоения Python 3 (стр. 120). О’Рейли СМИ.)

Как оказывается, это именно проблема Pagterterator решает. Это должно:

  • Итайте через некоторые данные. В этом случае страницы от ответа API.
  • Выдержать дополнительное состояние и функциональность пользователю. Например, отслеживать резюме токен что вызывающий абонент может использовать для возобновления прерванной пагинации. Или предложить Поиск Метод, который может найти записи, соответствующие A Jmespath выражение по страницам ответа.

Есть несколько удобных вещей под крышками Pagterterator сорт! Но в обычном случае, когда вы попадаете в петлю для цикла (или вызовите iTer () явно), он вызывает класс __iter __ () «Магический» метод за кулисами.

Итак, наверно, добыча, Pagterterator Является ли точное имя (позволяет вам повторять страницы) и вводящего в заблуждение один (он не поддерживает непосредственно протокол iTerator Python). Это больше ведет себя как потенциал :

Iterables можно использовать в цикле и во многих других местах, где требуется последовательность ( ZIP () , Карта () , …). Когда объект ITERABLE пропускается как аргумент в встроенной функции ИТЭР () он возвращает итератор для объекта. Этот итератор хороший для одного прохода над набором значений. При использовании iTerables обычно не нужно звонить ИТЭР () Или разобраться с объектами итератора. Заявление о том, что это автоматически для вас, создавая временную неназванную переменную для удержания итератора в течение длительности цикла. Смотрите также итератор, последовательность и генератор.

Trey Hunner делает отличную работу по поводу обсуждения этих концепций четко. Есть полезные разделы в обоих Протокол итератора: Как «за петли» работают в Python а также Как сделать итератор в Python которые имеют отношение к пониманию Pagterterator. ‘s поведение.

Для тех, кто сделал это так далеко и заинтересован в реальном коде, Pagterterator определяется здесь Отказ

Заворачивать

Я изначально написал этот пост на блоге внутренней компании пару лет назад. Я сделал несколько незначительных обновлений, но содержание в основном то же самое. Как я писал в то время, возможно, что я только думаю Я понимаю этот материал! Вопросы, комментарии и критика приветствуются в комментариях. Спасибо за прочтение!

Самое главное, если вы заметите любую откровенную ерунду здесь, пожалуйста, позвоните мне (публично или в частном порядке), чтобы я мог получить его, прежде чем ведать какие-либо невинные сбивцы с пути. Спасибо.

Оригинал: “https://dev.to/ajkerrigan/the-iterator-that-wasn-t-a-love-letter-to-boto3-paginators-1nc3”