DynamoDB UpdateItem en Python (boto3)
boto3 te donne deux clients pour cet appel, et ils ne sont pas d'accord sur ce qu'est un nombre. Le client bas niveau ci-dessous envoie et reçoit du JSON DynamoDB, où chaque nombre est une chaîne entre guillemets. resource("dynamodb").Table(...) prend des objets Python natifs, refuse catégoriquement float, et rend les nombres en decimal.Decimal. Le vrai choix de cette page, c'est de trancher entre les deux.
Code
import boto3
client = boto3.client("dynamodb")
response = client.update_item(
TableName="Music",
Key={"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}},
UpdateExpression="SET #upd0 = :updValue0, #upd1 = :updValue1 ADD #upd2 :updValue2",
ExpressionAttributeNames={"#upd0": "Genre", "#upd1": "Year", "#upd2": "Awards"},
ExpressionAttributeValues={":updValue0": {"S": "Latin Jazz"}, ":updValue1": {"N": "1994"}, ":updValue2": {"N": "1"}},
ReturnValues="ALL_NEW",
)
print(response["Attributes"]) # the item after the updateExplication
- La grammaire des clauses ne regarde pas boto3. L'
UpdateExpressionest une chaîne opaque qu'il transmet ; seul DynamoDB l'analyse, et les erreurs coûtent donc un aller-retour.ADDest ici l'incrément atomique qui supprime la course lecture-modification-écriture,attribute_exists(Artist)dans uneConditionExpressiontransforme l'upsert en mise à jour seule, et le reste est dans les expressions de mise à jour. - La réponse a exactement deux clés de premier niveau :
AttributesetResponseMetadata. Il n'y a aucun champ de statut à vérifier ni aucun nombre de lignes. Si l'appel a retourné, c'est que ça a marché ;ResponseMetadataporte leRequestIdet leHTTPStatusCodeque tu veux dans une ligne de log. ReturnValues="UPDATED_NEW"est l'option économe. Elle ne renvoie que les attributs que l'expression a touchés, ce qui, sur un gros élément, fait la différence entre relire un compteur et rapatrier tout l'enregistrement.- Les erreurs arrivent sous forme de
botocore.exceptions.ClientError, et tu branches sure.response["Error"]["Code"]. Un alias manquant produit uneValidationExceptionavec le messageInvalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: Year. Les sous-classes typées existent bien, mais uniquement comme attributs que botocore génère sur l'instance du client (client.exceptions.ConditionalCheckFailedException), jamais comme symboles importables : une fonction utilitaire qui n'a pas le client sous la main doit donc utiliser la chaîne du code.
Decimal ou JSON DynamoDB, il faut choisir
L'API resource rejette float avant même que la requête ne soit construite, avec un message qui dit exactement ce qu'elle veut :
TypeError: Float types are not supported. Use Decimal types instead.C'est le typage de boto3 lui-même, pas celui de DynamoDB. Stocke Decimal("4.5") via l'API resource, relis le même attribut avec les deux clients, et tu obtiens :
resource Rating: Decimal('4.5') Awards: Decimal('2')
client Rating: {'N': '4.5'} Awards: {'N': '2'}Aucun des deux n'a tort ; ce sont des contrats différents. Decimal conserve la précision que DynamoDB stocke réellement et t'oblige à réfléchir à l'arithmétique, au prix d'un Decimal("1") * 2 qui surgit dans du code qui attendait un int. Le client bas niveau te rend des chaînes et te laisse l'analyse, ce que fait le snippet ci-dessus.
La règle qui en découle : ne les mélange pas dans un même chemin de code. Un élément écrit via Table.put_item et lu via client.get_item revient sous une forme différente, et le bug apparaît dans la branche que tu as le moins testée.
Une note sur les attributs TTL
Le SET numérique le plus courant dans une base de code Python, c'est un TTL : SET expires_at = :t avec un timestamp Unix. DynamoDB lit cet attribut en secondes. Écris int(time.time() * 1000) à la place et la valeur vaut 1785269450912, ce qui, en secondes, tombe en l'an 58542 : l'élément n'est donc jamais supprimé et personne ne se plaint. Le convertisseur TTL DynamoDB relit un timestamp dans les deux unités et te dit laquelle tu as écrite. Pour relire ensuite la valeur stockée depuis une vraie table, télécharge DynoTable.
Guides liés
- Les expressions de mise à jour DynamoDB —
SET,ADD,REMOVE,DELETE, et les idiomes. - Comprendre ReturnValues — ce que t'apporte chaque option de
ReturnValues. - "Attribute name is a reserved keyword" — pourquoi la map d'alias n'est pas optionnelle ici.
- Les erreurs de syntaxe "Invalid UpdateExpression" — les erreurs de syntaxe SET/ADD courantes, décodées.
Références
- UpdateItem — Amazon DynamoDB API Reference
- update_item — Boto3 DynamoDB.Client Reference
- Update expressions — Amazon DynamoDB Developer Guide
Dernière vérification le 2026-07-28 par rapport à la documentation officielle AWS liée ci-dessus.