DynamoDB GetItem in Python (boto3)

get_item holt ein Item über seinen vollständigen Primary Key. Der boto3-Low-Level-Client (boto3.client("dynamodb")) spricht in beide Richtungen DynamoDB JSON, der Key geht also mit seinem Typ verpackt hinein und das Item kommt genauso zurück. Worin sich das von query und scan unterscheidet, steht in Item-basierte Aktionen.

Code

import boto3

client = boto3.client("dynamodb")

response = client.get_item(
    TableName="Music",
    Key={"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}},
    ProjectionExpression="#proj0, #proj1, #proj2, #proj3",
    ExpressionAttributeNames={"#proj0": "Artist", "#proj1": "SongTitle", "#proj2": "AlbumTitle", "#proj3": "Year"},
)

item = response.get("Item")
if item is None:
    print("Item not found")
else:
    print(item)

Erklärung

Ein Fehltreffer liefert eine Antwort ganz ohne Item-Key. Nicht None, kein leeres Dict. Beim Lesen derselben Tabelle mit einem Key, den es nicht gibt, waren die Top-Level-Keys der Antwort genau:

['ResponseMetadata']

Deshalb nutzt das Snippet response.get("Item"). response["Item"] wirft auf dem ganz normalen Nicht-gefunden-Pfad einen KeyError — so wird aus einer fehlenden Zeile ein 500er in einem Web-Handler. Berechnet wird dir der Read trotzdem: AWS' Seite zur Lesekapazität sagt, dass "if you perform a read operation on an item that doesn't exist, DynamoDB will still consume read throughput as outlined above" (abgerufen am 2026-07-28).

Year ist ein reserviertes Wort, weshalb das generierte Snippet jedes projizierte Attribut aliast. Lass die #proj-Aliasse weg und übergib ProjectionExpression="Year", und die Engine lehnt den Read ab:

ValidationException: Invalid ProjectionExpression: Attribute name is a reserved keyword; reserved keyword: Year

Bedingungslos zu aliasen kostet nichts und beseitigt die ganze Fehlerklasse. Die vollständige Liste ist 573 Wörter lang; siehe "Attribute name is a reserved keyword".

Vier Arten, den Key falsch zu machen, drei verschiedene Meldungen. Es lohnt sich, sie auseinanderzuhalten, denn keine davon ist der „provided key element does not match the schema"-Fehler, den man erwartet. Reproduziert gegen eine Music-Tabelle mit Artist (Partition) + SongTitle (Sort) als Key:

Was du übergeben hastWortgetreue ValidationException-Meldung
{"Artist": …} — Sort Key fehltThe number of conditions on the keys is invalid
{"Artist": …, "SongTitle": …, "Extra": …}The number of conditions on the keys is invalid
{"Artist": …, "Song": …} — falscher AttributnameOne of the required keys was not given a value
{"Artist": {"N": "1"}, …} — falscher TypOne or more parameter values were invalid: Type mismatch for key

Beachte, dass ein fehlendes und ein überzähliges Key-Attribut dieselbe Meldung erzeugen: „number of conditions" heißt also „du hast mir nicht exakt das Key-Schema übergeben", nicht „du hast zu wenige übergeben".

ProjectionExpression kürzt die Nutzlast, nicht die Rechnung. Ein rund 15 KB großes Item auf drei Arten mit ReturnConsumedCapacity="TOTAL" gelesen:

full item, eventually consistent          CapacityUnits: 2.0
ProjectionExpression="#y" (Year only)     CapacityUnits: 2.0
ProjectionExpression="#y" + ConsistentRead  CapacityUnits: 4.0

Die Projektion hat die Antwort von rund 15 KB auf eine einzige Zahl geschrumpft und an den Kosten nichts geändert. AWS sagt es unmissverständlich: "The number of capacity units consumed will be the same whether you request all of the attributes (the default behavior) or just some of them (using a projection expression)" (Query API Reference, abgerufen am 2026-07-28). ConsistentRead=True ist das einzige Flag auf dieser Liste, das die Zahl bewegt — und es verdoppelt sie. Wofür Projektionen tatsächlich gut sind, steht in Projection Expressions.

Die Resource-API ist ein anderer Vertrag, keine schönere Schreibweise. boto3.resource("dynamodb").Table("Music").get_item(...) gibt schlichtes Python zurück und jede Zahl als decimal.Decimal:

{'Artist': 'Arturo Sandoval', 'AlbumTitle': 'Danzon', 'Awards': Decimal('0'), 'Year': Decimal('1994'), 'SongTitle': 'Cubano Chant'}

Das schneidet in beide Richtungen. Über dieselbe API mit einem float zurückzuschreiben wirft, bevor die Anfrage deine Maschine verlässt:

TypeError: Float types are not supported. Use Decimal types instead.

Wenn dich das erwischt, steht die Lösung unter "Float types are not supported". Die eigentliche Falle ist, beide APIs in einer Codebasis zu mischen: Der Low-Level-Client nimmt bereitwillig ein {"N": "1.5"} an, das die Resource-API abgelehnt hätte.

Fehler kommen als botocore-Exceptions, und boto3 gibt ihnen echte Klassen. Auf 1.43.58 ist das bei einer fehlgeschlagenen Bedingung geworfene Objekt eine ConditionalCheckFailedException, eine Unterklasse von ClientError — sowohl except ClientError plus eine Prüfung auf err.response["Error"]["Code"] als auch except client.exceptions.ConditionalCheckFailedException funktionieren also. Nimm, was deine Codebasis ohnehin schon nutzt; matche nicht auf str(e).

Mach es visuell

Bevor du von Hand aliast: Der kostenlose DynamoDB-Reserved-Words-Checker nimmt deine Attributnamen, sagt dir, welche der 573 reservierten Wörter du triffst, und gibt die ExpressionAttributeNames-Map fertig zum Einfügen aus.

Um Tabellen zu durchsuchen und GetItem gegen deine eigenen Daten auszuführen — Key-Formular, Ergebnis-Grid, die Anfrage als boto3 zurückkopieren — lade DynoTable herunter.

Verwandte Leitfäden

Referenzen

Am 2026-07-28 gegen DynamoDB Local (amazon/dynamodb-local) auf Port 9000 mit boto3 1.43.58 / botocore 1.43.58 reproduziert. Jede Meldung und jede Kapazitätszahl oben ist Engine-Ausgabe, wortgetreu kopiert. DynamoDB Local ist nicht der Dienst; wo bekannt ist, dass beide einen Fehler unterschiedlich formulieren, sagen wir es auf der Fehlerseite.

Mit DynamoDB ohne die Console arbeiten

Ein schneller DynamoDB-Desktop-Client, der das echte SQL ausführt, das DynamoDB nicht kann — JOINs, GROUP BY, Aggregationen — mit visueller Bearbeitung und einem KI-Agenten auf deinen eigenen Bedrock-Schlüsseln.

30 Tage kostenlos testen, keine Kreditkarte — danach der Kostenlos-Tarif ohne Zeitlimit.