Mateus Müller

O carinha do Linux

25 mar. 2024

boto3: Pagination da API da AWS de forma fácil

Recentemente comecei a pesquisar mais sobre o uso do boto3, mais especificamente práticas como retry backoff, pagination, throttling, etc.

Foi então que encontrei uma forma muito fácil de trabalhar com pagination usando o boto3.

Mas começando pelo começo… O que é pagination?

Pense em uma chamada que retornaria 5000 itens do banco de dados. É uma query bastante pesada, e partindo do princípio que uma API única é usada por milhões de usuários, a query de um usuário pode impactar outros.

Então os providers limitam essa resposta em páginas. Ainda no exemplo acima, poderiam ser 5 páginas de 1000 itens. Dessa forma a gente dá uma “folga” pro banco de dados e garante que a API não vai cair.

Se você olhar a documentação de qualquer chamada de API da boto3, verá que a response vai voltar um NextToken ou NextContinuationToken. Por exemplo a list_objects_v2.

Esse token precisa ser usado na API call subsequente, e dessa forma o backend da AWS sabe que precisa retornar o próximo batch de dados.

Montei um snippet aqui e vou explicar para vocês:

#!/usr/bin/env python3

import boto3

session = boto3.Session(profile_name="profile-da-awscli")
client = session.client("s3")

paginator = client.get_paginator('list_objects_v2')

parameters = {
    'Bucket': 'nomedobucket',
    'MaxKeys': 10
}

page_iterator = paginator.paginate(**parameters)

for object in page_iterator:
    print("-------------- PAGINATED --------------")
    for key in object["Contents"]:
        print(key["Key"])

Todo client da boto3 possui isso implementado (pelo menos foi o que eu entendi rsrs). Usei o client do s3 porque tenho vários objetos dentro de um bucket, e seria bem mais fácil simular a paginação do mesmo.

Note o seguinte:

  1. client = session.client("s3") aqui eu inicializei o client do s3. Poderia ser qualquer outro serviço, como ec2, eks, ecs e por aí vai…
  2. paginator = client.get_paginator('list_objects_v2') aqui é onde a mágica acontece… Eu instancio um paginator usando o client do passo 1, e informando qual chamada de API vou querer paginar.

Aqui você consegue ver todas as chamadas do client S3 que poderiam ser paginadas. E novamente, o mesmo se aplica para qualquer outro client do boto3.

  1. Com isso em mente, eu já preparo os parâmetros que vou passar para o list_objects_v2: nome do bucket & quantidade de itens que quero limitar.
parameters = {
    'Bucket': 'nomedobucket',
    'MaxKeys': 10
}

Com isso eu garanto que somente 10 itens serão retornados, e o pagination vai acontecer. Estou forçando isso porque o limite dessa chamada é de 1000 itens, então se você tem menos dentro do bucket, certamente ele não vai paginar.

  1. E agora a chamada efetivamente:
page_iterator = paginator.paginate(**parameters)

Usamos o paginator que instanciamos no começo, informando o dict de parâmetros também instanciados acima. Ele vai paginar tudo para nós e retornar um iterator. Isso signicica que é só chamar um for e correr pro abraço.

for object in page_iterator:
    print("-------------- PAGINATED --------------")
    for key in object["Contents"]:
        print(key["Key"])

Para cada resposta dentro do paginator, eu preciso extrair qual é o nome da key (nome do objeto no s3).

Então a saída vai ser mais ou menos assim:

-------------- PAGINATED --------------
2018/07/30/personalizando-o-bash-com-jm-shell/index.html
2018/08/02/criando-gifs-animados-com-peek-no-linux/index.html
2018/08/07/conheca-todo-o-caminho-de-certificacoes-lpi/index.html
2018/08/09/unifique-seus-aplicativos-de-contato-com-o-franz/index.html
2018/08/14/tunando-seu-sistema-linux-com-tuned/index.html
2018/08/16/editando-arquivos-remotamente-com-o-visual-studio-code/index.html
2018/08/21/troque-as-planilhas-pelo-snipe-it-e-tenha-total-controle-dos-ativos-da-sua-empresa/index.html
2018/08/23/conheca-os-principais-programas-para-quem-quer-ser-blogger-ou-youtuber-usando-linux/index.html
2018/08/28/distribuicao-linux-da-intel-conheca-o-clear-linux-projetado-para-o-hardware-intel/index.html
2018/08/30/o-guia-definitivo-para-um-rsync-newbie/index.html
-------------- PAGINATED --------------
2018/09/04/os-10-melhores-atalhos-para-trabalhar-na-linha-de-comando-do-linux/index.html
2018/09/06/7-dicas-para-melhorar-a-performance-do-seu-linux-usando-ssd/index.html
2018/09/11/instalando-uma-interface-grafica-no-linux-centos-7/index.html
2018/09/13/solucionado-nao-e-possivel-editar-fotos-com-shutter-no-ubuntu-18-04/index.html
2018/09/18/como-deixar-o-centos-em-tela-cheia-no-virtual-box/index.html
2018/09/20/como-fazer-o-backup-das-suas-maquinas-virtuais-do-virtual-box-no-linux/index.html
2018/09/25/o-que-e-exfat-como-formatar-um-dispositivo-em-exfat-no-linux/index.html
2018/09/27/redes-sociais-em-somente-um-lugar-com-rambox/index.html
2018/10/02/filezilla-a-melhor-opcao-para-fazer-transferencia-de-arquivos-remota/index.html
2018/10/04/facilite-a-comunicacao-entre-sua-equipe-com-o-slack/index.html
...
...
...

Que são os nomes dos objetos (posts do meu blog rsrs) lá no s3. Sempre batches de 10 objetos separados por aquela string ali

Espero que ajude de alguma forma, grande abraço!

Buy me a coffeeBuy me a coffee
Comentários Disqus