DynamoDB UpdateItem in Python (boto3)
boto3 gibt dir für diesen Aufruf zwei Clients, und sie sind sich uneinig darüber, was eine Zahl ist. Der Low-Level-client unten sendet und empfängt DynamoDB JSON, wo jede Zahl ein String in Anführungszeichen ist. resource("dynamodb").Table(...) nimmt native Python-Objekte, verweigert float rundheraus und gibt Zahlen als decimal.Decimal zurück. Sich für einen zu entscheiden ist die eigentliche Entscheidung auf dieser Seite.
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 updateErklärung
- Die Klausel-Grammatik geht boto3 nichts an. Die
UpdateExpressionist ein opaker String, den es weiterreicht; nur DynamoDB parst sie, Fehler kosten also einen Round-Trip.ADDist hier das atomare Inkrement, das die Read-Modify-Write-Race beseitigt,attribute_exists(Artist)in einerConditionExpressionmacht aus dem Upsert ein reines Update, und der Rest steht in Update Expressions. - Die Antwort hat genau zwei Top-Level-Keys:
AttributesundResponseMetadata. Es gibt kein Statusfeld zu prüfen und keine Zeilenzahl. Wenn der Aufruf zurückkam, hat er funktioniert;ResponseMetadataträgt dieRequestIdund denHTTPStatusCode, die du in einer Log-Zeile haben willst. ReturnValues="UPDATED_NEW"ist die sparsame Option. Es liefert nur die Attribute zurück, die die Expression angefasst hat — bei einem großen Item ist das der Unterschied zwischen einem gelesenen Zähler und dem gesamten Datensatz auf dem Rückweg.- Fehler kommen als
botocore.exceptions.ClientError, und du verzweigst übere.response["Error"]["Code"]. Ein fehlender Alias erzeugt eineValidationExceptionmit der MeldungInvalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: Year. Die typisierten Unterklassen existieren zwar, aber nur als Attribute, die botocore auf der Client-Instanz erzeugt (client.exceptions.ConditionalCheckFailedException), nie als importierbare Symbole — eine Hilfsfunktion ohne Client im Scope muss also den Code-String verwenden.
Decimal oder DynamoDB JSON, entscheide dich
Die Resource-API lehnt float ab, bevor die Anfrage überhaupt gebaut wird, mit einer Meldung, die genau sagt, was sie will:
TypeError: Float types are not supported. Use Decimal types instead.Das ist boto3s eigene Typprüfung, nicht die von DynamoDB. Speichere Decimal("4.5") über die Resource-API und lies dasselbe Attribut über beide Clients zurück, und du bekommst:
resource Rating: Decimal('4.5') Awards: Decimal('2')
client Rating: {'N': '4.5'} Awards: {'N': '2'}Keines von beiden ist falsch; es sind verschiedene Verträge. Decimal behält die Präzision, die DynamoDB tatsächlich speichert, und zwingt dich, über Arithmetik nachzudenken — zum Preis, dass Decimal("1") * 2 in Code auftaucht, der ein int erwartet hat. Der Low-Level-Client gibt dir Strings und überlässt dir das Parsen, und genau das macht das Snippet oben.
Daraus folgt die Regel: Mische sie nicht in einem Codepfad. Ein über Table.put_item geschriebenes und über client.get_item gelesenes Item kommt in anderer Form zurück, und der Bug taucht in dem Zweig auf, den du weniger getestet hast.
Eine Anmerkung zu TTL-Attributen
Das häufigste numerische SET in einer Python-Codebasis ist ein TTL: SET expires_at = :t mit einem Unix-Epoch. DynamoDB liest dieses Attribut als Sekunden. Schreib stattdessen int(time.time() * 1000), und der Wert ist 1785269450912, was als Sekunden im Jahr 58542 landet — das Item wird also nie gelöscht und niemand beschwert sich. Der DynamoDB-TTL-Konverter liest einen Epoch-Wert in beiden Einheiten zurück und sagt dir, welche du geschrieben hast. Um den gespeicherten Wert danach aus einer echten Tabelle zurückzulesen, lade DynoTable herunter.
Verwandte Leitfäden
- DynamoDB Update Expressions —
SET,ADD,REMOVE,DELETEund die Idiome. - ReturnValues verstehen — was dir jede
ReturnValues-Option liefert. - "Attribute name is a reserved keyword" — warum die Alias-Map hier nicht optional ist.
- "Invalid UpdateExpression"-Syntaxfehler — die häufigen SET-/ADD-Syntaxfehler, entschlüsselt.
Referenzen
- UpdateItem — Amazon DynamoDB API Reference
- update_item — Boto3 DynamoDB.Client Reference
- Update expressions — Amazon DynamoDB Developer Guide
Zuletzt verifiziert am 2026-07-28 gegen die oben verlinkte offizielle AWS-Dokumentation.