DynamoDB BatchGetItem en Python (boto3)
batch_get_item recupera hasta 100 elementos por clave principal en una sola petición. El while request_items: del bloque de abajo es todo el idioma de boto3: DynamoDB te devuelve los pendientes en una respuesta correcta, y un diccionario vacío es falsy, así que el bucle se termina solo. Los límites y las reglas de resultados parciales viven en operaciones por lotes en DynamoDB; esta página trata de la llamada de boto3 y de los errores que lanza.
Código
import time
import boto3
client = boto3.client("dynamodb")
request_items = {
"Music": {
"Keys": [
{"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}},
{"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "A Mis Abuelos"}},
{"Artist": {"S": "Ella Fitzgerald"}, "SongTitle": {"S": "Misty"}},
]
}
}
items = []
attempt = 0
while request_items:
response = client.batch_get_item(RequestItems=request_items)
items.extend(response["Responses"].get("Music", []))
# A partial result is NOT an error: throttling, a >16 MB response, or an
# internal failure returns the leftovers in UnprocessedKeys. Retry them
# with exponential backoff.
request_items = response["UnprocessedKeys"]
if request_items:
attempt += 1
time.sleep(min(0.1 * 2**attempt, 5))
print(f"Fetched {len(items)} items")Explicación
response["UnprocessedKeys"]siempre está. En un lote servido por completo la clave existe y contiene{}, así querequest_items = response["UnprocessedKeys"]es seguro de indexar y el diccionario vacío falsy es lo que termina elwhile. ConResponseshay que tener más cuidado: una tabla cuyas claves fallaron todas simplemente no aparece, y por eso el bloque usa.get("Music", []).ConsistentReadyProjectionExpressionvan dentro del diccionario de cada tabla, junto a"Keys", no al lado deRequestItems. boto3 enviará encantado una clave mal colocada y dejará que el servicio la rechace.- Este es el cliente de bajo nivel, así que los valores son JSON de DynamoDB (
{"S": ...},{"N": ...}). La API de recursos tienebatch_get_itemen el ServiceResource, no enTable.boto3.resource("dynamodb").batch_get_item(...)acepta valores nativos de Python;table.batch_get_itemno existe. Esa asimetría sorprende a quien lo busca después de usartable.batch_writer(), que sí es un método deTable. - El backoff se aplica solo a
UnprocessedKeys. UnaValidationExceptiones un error en la petición, y reintentarla solo quema tiempo.
Los dos errores que lanza esta llamada, literales
Ambos son fallos del lado del cliente que ningún reintento arregla, y ambos aparecen como un simple botocore.exceptions.ClientError. Contra DynamoDB Local 3.3.0, str(e):
An error occurred (ValidationException) when calling the BatchGetItem operation: Too many items requested for the BatchGetItem call
An error occurred (ValidationException) when calling the BatchGetItem operation: Provided list of item keys contains duplicatesEl primero son 101 claves, el segundo es la misma clave listada dos veces. Fíjate en lo que no puedes escribir para capturarlos:
except client.exceptions.ValidationException: # AttributeErrorbotocore modela 34 clases de excepción con nombre en el cliente de DynamoDB, y ValidationException no es una de ellas. ConditionalCheckFailedException y ProvisionedThroughputExceededException sí lo son, y por eso la página de escritura condicional puede capturar por clase y esta no. Existe incluso una DuplicateItemException modelada, y no es lo que te da una clave duplicada en un lote. Así que una lectura por lotes tiene que ramificar según el código:
except ClientError as e:
if e.response["Error"]["Code"] == "ValidationException":
raise # a bug in the request; retrying will not helpEl caso de la clave duplicada es el que muerde en código real, porque una lista de claves montada a partir de un resultado de Query o de una tabla de unión repite con naturalidad. Deduplica antes de enviar, recordando que dos diccionarios son iguales solo si coincide cada atributo de clave.
El tamaño es la otra razón por la que un lote de 100 no sigue siendo un lote de 100: cada elemento se redondea a 4 KB para la facturación y cuenta contra los 16 MB de la respuesta, así que 100 elementos de 300 KB vuelven como unos 52 y el resto en UnprocessedKeys. La calculadora de tamaño de elemento te da la cifra por elemento que hay que multiplicar.
Para traerte de vuelta un conjunto de claves e inspeccionar lo que devolvió antes de escribir el bucle, descarga DynoTable.
Ejemplos relacionados
- DynamoDB BatchGetItem en Node.js — la misma lectura por lotes con AWS SDK v3.
- DynamoDB BatchGetItem con la AWS CLI — la misma lectura por lotes desde el shell.
- DynamoDB GetItem en Python — la lectura de un solo elemento que esto agrupa.
- Operaciones por lotes en DynamoDB — límites, fallos parciales y cuándo compensa agrupar.
- "Too many items requested for the BatchGetItem call" — más de 100 claves en una sola petición.
- "Provided list of item keys contains duplicates" — la misma clave dos veces en un lote.
Referencias
- BatchGetItem — Amazon DynamoDB API Reference
- DynamoDB.Client.batch_get_item — Boto3 documentation
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
Verificado por última vez el 2026-07-28 contra la documentación oficial de AWS enlazada arriba.