Programmieren von Amazon DynamoDB mit Python und Boto3 - Amazon-DynamoDB

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Programmieren von Amazon DynamoDB mit Python und Boto3

Dieses Handbuch bietet Programmierern, die Amazon DynamoDB mit Python verwenden möchten, eine Orientierung. Erfahren Sie mehr über die verschiedenen Abstraktionsebenen, das Konfigurationsmanagement, die Fehlerbehandlung, die Steuerung von Wiederholungsrichtlinien, die Verwaltung von Keep-Alive und mehr.

Über Boto

Sie können von Python aus auf DynamoDB zugreifen, indem Sie das offizielle AWS SDK für Python verwenden, das allgemein als Boto3 bezeichnet wird. Der Name Boto (ausgesprochen boh-toh) stammt von einem Süßwasserdelfin, der im Amazon heimisch ist. Die Boto3-Bibliothek ist die dritte Hauptversion der Bibliothek, die erstmals 2015 veröffentlicht wurde. Die Boto3-Bibliothek ist ziemlich groß, da sie alle AWS Dienste unterstützt, nicht nur DynamoDB. Diese Ausrichtung zielt nur auf die Teile von Boto3 ab, die für DynamoDB relevant sind.

Boto wird von einem Open-Source-Projekt verwaltet und veröffentlicht, das auf gehostet wird AWS . GitHub Es ist in zwei Pakete aufgeteilt: Botocore und Boto3.

  • Botocore bietet die Low-Level-Funktionalität. In Botocore finden Sie die Klassen Client, Session, Credentials, Config und Exception.

  • Boto3 baut auf Botocore auf. Es bietet eine übergeordnete, pythonischere Oberfläche. Insbesondere macht es eine DynamoDB-Tabelle als Ressource verfügbar und bietet eine einfachere, elegantere Oberfläche als die serviceorientierte Client-Schnittstelle auf niedrigerer Ebene.

Da diese Projekte auf gehostet werden GitHub, können Sie den Quellcode einsehen, offene Probleme verfolgen oder Ihre eigenen Probleme einreichen.

Verwenden Sie die Boto-Dokumentation

Beginnen Sie mit der Boto-Dokumentation mit den folgenden Ressourcen:

  • Beginnen Sie mit dem Abschnitt Schnellstart, der einen soliden Ausgangspunkt für die Paketinstallation bietet. Dort finden Sie Anweisungen zur Installation von Boto3, falls dies noch nicht geschehen ist (Boto3 ist häufig automatisch in AWS Diensten wie) verfügbar. AWS Lambda

  • Konzentrieren Sie sich danach auf den DynamoDB-Leitfaden der Dokumentation. Es zeigt Ihnen, wie Sie die grundlegenden DynamoDB-Aktivitäten ausführen: eine Tabelle erstellen und löschen, Elemente bearbeiten, Batch-Operationen ausführen, eine Abfrage ausführen und einen Scan durchführen. Die Beispiele verwenden die Ressourcenschnittstelle. Wenn Sie boto3.resource('dynamodb') das sehen, bedeutet das, dass Sie die übergeordnete Ressourcenschnittstelle verwenden.

  • Nach dem Leitfaden können Sie sich die DynamoDB-Referenz ansehen. Diese Landing Page bietet eine vollständige Liste der Klassen und Methoden, die Ihnen zur Verfügung stehen. Oben sehen Sie die DynamoDB.Client Klasse. Dies bietet einfachen Zugriff auf alle Operationen auf der Steuerungsebene und der Datenebene. Schauen Sie sich unten die Klasse an. DynamoDB.ServiceResource Dies ist die Pythonic-Schnittstelle auf höherer Ebene. Damit können Sie eine Tabelle erstellen, tabellenübergreifende Batch-Operationen ausführen oder eine DynamoDB.ServiceResource.Table Instanz für tabellenspezifische Aktionen abrufen.

Grundlegendes zu den Client- und Ressourcenabstraktionsebenen

Die beiden Schnittstellen, mit denen Sie arbeiten werden, sind die Client-Schnittstelle und die Ressourcenschnittstelle.

  • Die Low-Level-Client-Schnittstelle bietet eine 1-zu-1-Zuordnung zur zugrunde liegenden Service-API. Jede von DynamoDB angebotene API ist über den Client verfügbar. Das bedeutet, dass die Client-Schnittstelle vollständige Funktionalität bieten kann, aber sie ist oft ausführlicher und komplexer zu verwenden.

  • Die übergeordnete Ressourcenschnittstelle bietet keine 1-zu-1-Zuordnung der zugrunde liegenden Service-API. Es bietet jedoch Methoden, die Ihnen den Zugriff auf den Dienst erleichtern, z. batch_writer

Hier ist ein Beispiel für das Einfügen eines Elements über die Client-Schnittstelle. Beachten Sie, dass alle Werte als Map übergeben werden, wobei der Schlüssel ihren Typ ('S' für Zeichenfolge, 'N' für Zahl) und ihren Wert als Zeichenfolge angibt. Dies wird als DynamoDB-JSON-Format bezeichnet.

import boto3 dynamodb = boto3.client('dynamodb') dynamodb.put_item( TableName='YourTableName', Item={ 'pk': {'S': 'id#1'}, 'sk': {'S': 'cart#123'}, 'name': {'S': 'SomeName'}, 'inventory': {'N': '500'}, # ... more attributes ... } )

Hier ist derselbe PutItem Vorgang, der die Ressourcenschnittstelle verwendet. Die Datentypisierung ist implizit:

import boto3 dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('YourTableName') table.put_item( Item={ 'pk': 'id#1', 'sk': 'cart#123', 'name': 'SomeName', 'inventory': 500, # ... more attributes ... } )

Bei Bedarf können Sie mithilfe der in boto3 bereitgestellten TypeDeserializer Klassen und zwischen normalem JSON TypeSerializer und DynamoDB-JSON konvertieren:

def dynamo_to_python(dynamo_object: dict) -> dict: deserializer = TypeDeserializer() return { k: deserializer.deserialize(v) for k, v in dynamo_object.items() } def python_to_dynamo(python_object: dict) -> dict: serializer = TypeSerializer() return { k: serializer.serialize(v) for k, v in python_object.items() }

So führen Sie eine Abfrage mithilfe der Client-Schnittstelle durch. Es drückt die Abfrage als JSON-Konstrukt aus. Es verwendet eine KeyConditionExpression Zeichenfolge, die eine Variablenersetzung erfordert, um mögliche Schlüsselwortkonflikte zu behandeln:

import boto3 client = boto3.client('dynamodb') # Construct the query response = client.query( TableName='YourTableName', KeyConditionExpression='pk = :pk_val AND begins_with(sk, :sk_val)', FilterExpression='#name = :name_val', ExpressionAttributeValues={ ':pk_val': {'S': 'id#1'}, ':sk_val': {'S': 'cart#'}, ':name_val': {'S': 'SomeName'}, }, ExpressionAttributeNames={ '#name': 'name', } )

Derselbe Abfragevorgang, der die Ressourcenschnittstelle verwendet, kann verkürzt und vereinfacht werden:

import boto3 from boto3.dynamodb.conditions import Key, Attr dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('YourTableName') response = table.query( KeyConditionExpression=Key('pk').eq('id#1') & Key('sk').begins_with('cart#'), FilterExpression=Attr('name').eq('SomeName') )

Stellen Sie sich als letztes Beispiel vor, Sie möchten die ungefähre Größe einer Tabelle ermitteln (das sind Metadaten, die in der Tabelle gespeichert sind und etwa alle 6 Stunden aktualisiert werden). Mit der Client-Schnittstelle führen Sie eine describe_table() Operation aus und ziehen die Antwort aus der zurückgegebenen JSON-Struktur ab:

import boto3 dynamodb = boto3.client('dynamodb') response = dynamodb.describe_table(TableName='YourTableName') size = response['Table']['TableSizeBytes']

Mit der Ressourcenschnittstelle führt die Tabelle die Beschreibungsoperation implizit aus und präsentiert die Daten direkt als Attribut:

import boto3 dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('YourTableName') size = table.table_size_bytes
Anmerkung

Beachten Sie bei der Entscheidung, ob Sie mit der Client- oder der Ressourcenschnittstelle entwickeln möchten, dass der Ressourcenschnittstelle gemäß der Ressourcendokumentation keine neuen Funktionen hinzugefügt werden: „Das AWS Python SDK-Team beabsichtigt nicht, der Ressourcenschnittstelle in boto3 neue Funktionen hinzuzufügen. Bestehende Schnittstellen werden während des Lebenszyklus von boto3 weiterhin funktionieren. Kunden können über die Client-Oberfläche auf neuere Servicefunktionen zugreifen.“

Verwenden Sie die Tabellenressource batch_writer

Ein Vorteil, der nur mit der Tabellenressource auf höherer Ebene verfügbar ist, ist der. batch_writer DynamoDB unterstützt Batch-Schreibvorgänge und ermöglicht bis zu 25 Put- oder Löschvorgänge in einer Netzwerkanforderung. Eine solche Batchverarbeitung verbessert die Effizienz, da Netzwerk-Roundtrips minimiert werden.

Mit der Low-Level-Clientbibliothek verwenden Sie den client.batch_write_item() Vorgang, um Batches auszuführen. Sie müssen Ihre Arbeit manuell in Stapel von 25 aufteilen. Nach jedem Vorgang müssen Sie außerdem eine Liste der unverarbeiteten Elemente anfordern (einige Schreibvorgänge können erfolgreich sein, während andere fehlschlagen könnten). Anschließend müssen Sie diese unverarbeiteten Elemente erneut an einen späteren batch_write_item() Vorgang übergeben. Es gibt eine beträchtliche Menge an Standardcode.

Die Methode Table.BATCH_WRITER erstellt einen Kontextmanager zum Schreiben von Objekten in einem Batch. Sie stellt eine Schnittstelle dar, in der es den Anschein hat, als würden Sie die Elemente einzeln schreiben, aber intern puffert und sendet sie stapelweise. Es verarbeitet auch implizite Wiederholungen unverarbeiteter Elemente.

dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('YourTableName') movies = # long list of movies in {'pk': 'val', 'sk': 'val', etc} format with table.batch_writer() as writer: for movie in movies: writer.put_item(Item=movie)

Zusätzliche Codebeispiele, die die Client- und Ressourcenebene untersuchen

Sie können sich auch auf die folgenden Codebeispiel-Repositorys beziehen, die die Verwendung der verschiedenen Funktionen untersuchen, wobei sowohl der Client als auch die Ressource verwendet werden:

Verstehen, wie die Client- und Resource-Objekte mit Sitzungen und Threads interagieren

Das Resource-Objekt ist nicht threadsicher und sollte nicht von Threads oder Prozessen gemeinsam genutzt werden. Weitere Informationen finden Sie im Leitfaden zu Resource.

Das Client-Objekt ist dagegen im Allgemeinen Thread-sicher, mit Ausnahme bestimmter erweiterter Funktionen. Weitere Informationen finden Sie im Leitfaden zu Clients.

Das Session-Objekt ist nicht threadsicher. Jedes Mal, wenn Sie einen Client oder eine Ressource in einer Multithread-Umgebung erstellen, sollten Sie also zuerst eine neue Sitzung erstellen und dann den Client oder die Ressource aus der Sitzung erstellen. Weitere Informationen finden Sie im Leitfaden zu Sitzungen.

Wenn Sie die aufrufenboto3.resource(), verwenden Sie implizit die Standardsitzung. Dies ist praktisch, wenn Sie Single-Thread-Code schreiben möchten. Wenn Sie Multithread-Code schreiben, sollten Sie zunächst für jeden Thread eine neue Sitzung erstellen und dann die Ressource aus dieser Sitzung abrufen:

# Explicitly create a new Session for this thread session = boto3.Session() dynamodb = session.resource('dynamodb')

Anpassen des Config-Objekts

Wenn Sie ein Client- oder Resource-Objekt erstellen, können Sie optionale benannte Parameter übergeben, um das Verhalten anzupassen. Der angegebene Parameter config entsperrt eine Vielzahl von Funktionen. Es ist eine Instanz von botocore.client.Config und die Referenzdokumentation für Config zeigt alles, was es Ihnen zur Steuerung zur Verfügung stellt. Die Anleitung zur Konfiguration bietet einen guten Überblick.

Anmerkung

Sie können viele dieser Verhaltenseinstellungen auf Sitzungsebene, in der AWS Konfigurationsdatei oder als Umgebungsvariablen ändern.

Config für Timeouts

Eine benutzerdefinierte Konfiguration kann unter anderem verwendet werden, um das Netzwerkverhalten anzupassen:

  • connect_timeout (float oder int) — Die Zeit in Sekunden, bis eine Timeout-Ausnahme ausgelöst wird, wenn versucht wird, eine Verbindung herzustellen. Standardmäßig ist ein Zeitraum von 60 Sekunden festgelegt.

  • read_timeout (float oder int) — Die Zeit in Sekunden, bis beim Versuch, aus einer Verbindung zu lesen, eine Timeout-Ausnahme ausgelöst wird. Standardmäßig ist ein Zeitraum von 60 Sekunden festgelegt.

Timeouts von 60 Sekunden sind für DynamoDB zu hoch. Das bedeutet, dass ein vorübergehender Netzwerkfehler den Client um eine Minute verzögert, bevor er es erneut versuchen kann. Der folgende Code verkürzt die Timeouts auf eine Sekunde:

import boto3 from botocore.config import Config my_config = Config( connect_timeout = 1.0, read_timeout = 1.0 ) dynamodb = boto3.resource('dynamodb', config=my_config)

Weitere Informationen zu Timeouts finden Sie unter Tuning der AWS Java SDK-HTTP-Anforderungseinstellungen für latenzbewusste DynamoDB-Anwendungen. Beachten Sie, dass das Java-SDK mehr Timeout-Konfigurationen als Python hat.

Config für Keep-Alive

Wenn Sie Botocore 1.27.84 oder höher verwenden, können Sie auch TCP Keep-Alive steuern:

  • tcp_keepalive (bool) — Aktiviert die TCP-Keep-Alive-Socket-Option, die beim Erstellen neuer Verbindungen verwendet wird, wenn sie auf gesetzt ist (standardmäßig). True False Dies ist nur ab Botocore 1.27.84 verfügbar.

Wenn Sie TCP Keep-Alive auf einstellen, können Sie die durchschnittlichen Latenzen reduzieren. True Hier ist ein Beispielcode, der TCP Keep-Alive bedingt auf true setzt, wenn Sie die richtige Botocore-Version haben:

import botocore import boto3 from botocore.config import Config from distutils.version import LooseVersion required_version = "1.27.84" current_version = botocore.__version__ my_config = Config( connect_timeout = 0.5, read_timeout = 0.5 ) if LooseVersion(current_version) > LooseVersion(required_version): my_config = my_config.merge(Config(tcp_keepalive = True)) dynamodb = boto3.resource('dynamodb', config=my_config)
Anmerkung

TCP Keep-Alive unterscheidet sich von HTTP Keep-Alive. Bei TCP Keep-Alive werden kleine Pakete vom zugrunde liegenden Betriebssystem über die Socket-Verbindung gesendet, um die Verbindung aufrechtzuerhalten und etwaige Unterbrechungen sofort zu erkennen. Mit HTTP Keep-Alive wird die auf dem zugrunde liegenden Socket aufgebaute Webverbindung wiederverwendet. HTTP Keep-Alive ist mit boto3 immer aktiviert.

Es gibt eine Grenze dafür, wie lange eine inaktive Verbindung aufrechterhalten werden kann. Erwägen Sie das Senden von regelmäßigen Anfragen (z. B. jede Minute), wenn Sie eine inaktive Verbindung haben, aber möchten, dass die nächste Anfrage eine bereits bestehende Verbindung verwendet.

Config für Wiederholungsversuche

Die Konfiguration akzeptiert auch ein Wörterbuch namens Wiederholungen, in dem Sie Ihr gewünschtes Wiederholungsverhalten angeben können. Wiederholungen finden innerhalb des SDK statt, wenn das SDK einen Fehler empfängt und der Fehler vorübergehend ist. Wenn ein Fehler intern wiederholt wird (und ein erneuter Versuch letztendlich zu einer erfolgreichen Antwort führt), liegt aus Sicht des aufrufenden Codes kein Fehler vor, sondern lediglich eine leicht erhöhte Latenz. Hier sind die Werte, die Sie angeben können:

  • max_attempts — Eine Ganzzahl, die die maximale Anzahl von Wiederholungsversuchen angibt, die bei einer einzelnen Anfrage durchgeführt werden. Wenn Sie diesen Wert beispielsweise auf 2 setzen, wird die Anfrage nach der ersten Anfrage höchstens zweimal wiederholt. Wenn Sie diesen Wert auf 0 setzen, werden nach der ersten Anfrage keine Wiederholungsversuche mehr versucht.

  • total_max_attempts — Eine Ganzzahl, die die maximale Gesamtzahl der Versuche angibt, die bei einer einzelnen Anfrage unternommen werden. Dies schließt die erste Anfrage ein, sodass ein Wert von 1 bedeutet, dass keine Anfragen erneut versucht werden. Wenn total_max_attempts und beide bereitgestellt max_attempts werden, hat dies total_max_attempts Vorrang. total_max_attemptswird vorgezogenmax_attempts, weil es der AWS_MAX_ATTEMPTS Umgebungsvariablen und dem Wert der max_attempts Konfigurationsdatei zugeordnet ist.

  • mode — Eine Zeichenfolge, die den Typ des Wiederholungsmodus darstellt, den Botocore verwenden sollte. Gültige Werte für sind:

    • legacy — Der Standardmodus. Wartet 50 ms bei der ersten Wiederholung und verwendet dann einen exponentiellen Backoff mit einem Basisfaktor von 2. Für DynamoDB führt es insgesamt bis zu 10 maximale Versuche durch (sofern nicht durch die oben genannten Änderungen überschrieben).

      Anmerkung

      Bei exponentiellem Backoff dauert der letzte Versuch fast 13 Sekunden.

    • Standard — Wird als Standard bezeichnet, weil er konsistenter mit anderen SDKs ist. AWS Wartet eine zufällige Zeit zwischen 0 ms und 1.000 ms auf den ersten Wiederholungsversuch. Wenn ein weiterer Versuch erforderlich ist, wählt es eine weitere zufällige Zeit zwischen 0 ms und 1.000 ms und multipliziert sie mit 2. Wenn ein weiterer Versuch erforderlich ist, erfolgt dieselbe zufällige Auswahl, multipliziert mit 4 usw. Jede Wartezeit ist auf 20 Sekunden begrenzt. In diesem Modus werden Wiederholungsversuche bei mehr erkannten Fehlerzuständen durchgeführt als im legacy Modus. Für DynamoDB führt es insgesamt bis zu 3 maximale Versuche durch (sofern nicht durch die oben genannten Änderungen überschrieben).

    • adaptiv — Ein experimenteller Wiederholungsmodus, der alle Funktionen des Standardmodus beinhaltet, aber eine automatische clientseitige Drosselung hinzufügt. Mit adaptiver Ratenbegrenzung können SDKs die Geschwindigkeit, mit der Anfragen gesendet werden, verlangsamen, um der Kapazität der Dienste besser gerecht zu werden. AWS Dies ist ein vorläufiger Modus, dessen Verhalten sich ändern kann.

Eine erweiterte Definition dieser Wiederholungsmodi finden Sie in der Anleitung zu Wiederholungsversuchen sowie im Thema Wiederholungsverhalten in der SDK-Referenz.

Hier ist ein Beispiel, das explizit die legacy Wiederholungsrichtlinie mit insgesamt maximal 3 Anfragen (2 Wiederholungen) verwendet:

import boto3 from botocore.config import Config my_config = Config( connect_timeout = 1.0, read_timeout = 1.0, retries = { 'mode': 'legacy', 'total_max_attempts': 3 } ) dynamodb = boto3.resource('dynamodb', config=my_config)

Da es sich bei DynamoDB um ein System mit hoher Verfügbarkeit und geringer Latenz handelt, sollten Sie bei der Geschwindigkeit von Wiederholungsversuchen möglicherweise etwas aggressiver vorgehen, als es die integrierten Wiederholungsrichtlinien zulassen. Sie können Ihre eigene Wiederholungsrichtlinie implementieren, indem Sie die maximale Anzahl der Versuche auf 0 setzen, die Ausnahmen selbst abfangen und es gegebenenfalls in Ihrem eigenen Code erneut versuchen, anstatt sich bei impliziten Wiederholungsversuchen auf boto3 zu verlassen.

Wenn Sie Ihre eigene Wiederholungsrichtlinie verwalten, sollten Sie zwischen Drosselungen und Fehlern unterscheiden:

  • Eine Drosselung (gekennzeichnet durch ein ProvisionedThroughputExceededException oderThrottlingException) weist auf einen fehlerfreien Dienst hin, der Sie darüber informiert, dass Sie Ihre Lese- oder Schreibkapazität in einer DynamoDB-Tabelle oder Partition überschritten haben. Mit jeder Millisekunde, die vergeht, wird etwas mehr Lese- oder Schreibkapazität zur Verfügung gestellt, sodass Sie schnell (z. B. alle 50 ms) erneut versuchen können, auf die neu freigegebene Kapazität zuzugreifen. Bei Drosselungen ist kein exponentieller Back-off erforderlich, da Drosselungen für DynamoDB leicht sind und keine Gebühren pro Anfrage für Sie anfallen. Exponential Backoff weist Client-Threads, die bereits am längsten gewartet haben, längere Verzögerungen zu, wodurch p50 und p99 statistisch gesehen nach außen ausgedehnt werden.

  • Ein Fehler (unter anderem durch ein InternalServerError oder a gekennzeichnet) weist auf ein ServiceUnavailable vorübergehendes Problem mit dem Dienst hin. Dies kann für die gesamte Tabelle oder möglicherweise nur für die Partition gelten, von der Sie lesen oder in die Sie schreiben. Bei Fehlern können Sie vor den Wiederholungsversuchen eine längere Pause einlegen (z. B. 250 ms oder 500 ms) und die Wiederholungsversuche mithilfe von Jitter gestaffelt durchführen.

Config für maximale Poolverbindungen

Schließlich können Sie mit der Konfiguration die Größe des Verbindungspools steuern:

  • max_pool_connections (int) — Die maximale Anzahl von Verbindungen, die in einem Verbindungspool beibehalten werden sollen. Wenn dieser Wert nicht festgelegt ist, wird der Standardwert 10 verwendet.

Diese Option steuert die maximale Anzahl von HTTP-Verbindungen, die zur Wiederverwendung gepoolt werden sollen. Pro Sitzung wird ein anderer Pool verwaltet. Wenn Sie davon ausgehen, dass mehr als 10 Threads gegen Clients oder Ressourcen gerichtet sind, die auf derselben Sitzung basieren, sollten Sie erwägen, diese Option zu erhöhen, sodass Threads nicht auf andere Threads warten müssen, die eine Poolverbindung verwenden.

import boto3 from botocore.config import Config my_config = Config( max_pool_connections = 20 ) # Setup a single session holding up to 20 pooled connections session = boto3.Session(my_config) # Create up to 20 resources against that session for handing to threads # Notice the single-threaded access to the Session and each Resource resource1 = session.resource('dynamodb') resource2 = session.resource('dynamodb') # etc

Fehlerbehandlung

AWS Nicht alle Serviceausnahmen sind in Boto3 statisch definiert. Dies liegt daran, dass Fehler und Ausnahmen bei AWS Diensten sehr unterschiedlich sind und sich ändern können. Boto3 verpackt alle Serviceausnahmen als a ClientError und stellt die Details als strukturiertes JSON zur Verfügung. Eine Fehlerantwort könnte beispielsweise wie folgt strukturiert sein:

{ 'Error': { 'Code': 'SomeServiceException', 'Message': 'Details/context around the exception or error' }, 'ResponseMetadata': { 'RequestId': '1234567890ABCDEF', 'HostId': 'host ID data will appear here as a hash', 'HTTPStatusCode': 400, 'HTTPHeaders': {'header metadata key/values will appear here'}, 'RetryAttempts': 0 } }

Der folgende Code fängt alle ClientError Ausnahmen ab und untersucht den Zeichenkettenwert von within of, Error um zu bestimmen, welche Aktion ausgeführt werden soll: Code

import botocore import boto3 dynamodb = boto3.client('dynamodb') try: response = dynamodb.put_item(...) except botocore.exceptions.ClientError as err: print('Error Code: {}'.format(err.response['Error']['Code'])) print('Error Message: {}'.format(err.response['Error']['Message'])) print('Http Code: {}'.format(err.response['ResponseMetadata']['HTTPStatusCode'])) print('Request ID: {}'.format(err.response['ResponseMetadata']['RequestId'])) if err.response['Error']['Code'] in ('ProvisionedThroughputExceededException', 'ThrottlingException'): print("Received a throttle") elif err.response['Error']['Code'] == 'InternalServerError': print("Received a server error") else: raise err

Einige (aber nicht alle) Ausnahmecodes wurden als Klassen der obersten Ebene materialisiert. Sie können sich dafür entscheiden, diese direkt zu behandeln. Wenn Sie die Client-Schnittstelle verwenden, werden diese Ausnahmen dynamisch auf Ihrem Client aufgefüllt und Sie catch diese Ausnahmen mithilfe Ihrer Client-Instanz ab, wie folgt:

except ddb_client.exceptions.ProvisionedThroughputExceededException:

Wenn Sie die Resource-Schnittstelle verwenden, müssen Sie die Verbindung von der Ressource .meta.client zum zugrundeliegenden Client verwenden, um auf die Ausnahmen zuzugreifen, und zwar wie folgt:

except ddb_resource.meta.client.exceptions.ProvisionedThroughputExceededException:

Um die Liste der materialisierten Ausnahmetypen zu überprüfen, können Sie die Liste dynamisch generieren:

ddb = boto3.client("dynamodb") print([e for e in dir(ddb.exceptions) if e.endswith('Exception') or e.endswith('Error')])

Wenn Sie einen Schreibvorgang mit einem Bedingungsausdruck ausführen, können Sie verlangen, dass der Wert des Elements in der Fehlerantwort zurückgegeben wird, falls der Ausdruck fehlschlägt.

try: response = table.put_item( Item=item, ConditionExpression='attribute_not_exists(pk)', ReturnValuesOnConditionCheckFailure='ALL_OLD' ) except table.meta.client.exceptions.ConditionalCheckFailedException as e: print('Item already exists:', e.response['Item'])

Weitere Informationen zur Fehlerbehandlung und zu Ausnahmen finden Sie unter:

Protokollierung

Die boto3-Bibliothek ist in das integrierte Logging-Modul von Python integriert, um zu verfolgen, was während einer Sitzung passiert. Um die Protokollierungsebenen zu steuern, können Sie das Logging-Modul konfigurieren:

import logging logging.basicConfig(level=logging.INFO)

Dadurch wird der Root-Logger so konfiguriert, dass er Nachrichten INFO und höhere Ebenen protokolliert. Logging-Nachrichten, die weniger schwerwiegend sind als Level 4, werden ignoriert. Zu den Protokollierungsebenen gehören DEBUG INFOWARNING,ERROR,, undCRITICAL. Der Standardwert ist WARNING.

Die Logger in boto3 sind hierarchisch. Die Bibliothek verwendet einige verschiedene Logger, die jeweils unterschiedlichen Teilen der Bibliothek entsprechen. Sie können das Verhalten der einzelnen Optionen separat steuern:

  • boto3: Der Hauptlogger für das boto3-Modul.

  • botocore: Der Hauptlogger für das Botocore-Paket.

  • botocore.auth: Wird zum Protokollieren der Signaturerstellung für Anfragen verwendet. AWS

  • botocore.credentials: Wird zum Protokollieren des Abrufs und der Aktualisierung von Anmeldeinformationen verwendet.

  • botocore.endpoint: Wird verwendet, um die Erstellung von Anfragen zu protokollieren, bevor sie über das Netzwerk gesendet werden.

  • botocore.hooks: Wird zum Protokollieren von Ereignissen verwendet, die in der Bibliothek ausgelöst wurden.

  • botocore.loaders: Wird zum Protokollieren verwendet, wenn Teile von Servicemodellen geladen werden. AWS

  • botocore.parsers: Wird zum Protokollieren von Serviceantworten verwendet, bevor sie analysiert werden. AWS

  • botocore.retryhandler: Wird zum Protokollieren der Verarbeitung von erneuten Versuchen von Serviceanfragen verwendet (Legacy-Modus). AWS

  • botocore.retries.standard: Wird zum Protokollieren der Verarbeitung von erneuten Versuchen von Serviceanfragen verwendet (Standard- oder adaptiver Modus). AWS

  • botocore.utils: Wird zum Protokollieren verschiedener Aktivitäten in der Bibliothek verwendet.

  • botocore.waiter: Wird verwendet, um die Funktionalität von Kellnern zu protokollieren, die einen Dienst abfragen, bis ein bestimmter Status erreicht ist. AWS

Andere Bibliotheken protokollieren ebenfalls. Intern verwendet boto3 die URLlib3 eines Drittanbieters für die HTTP-Verbindungsverarbeitung. Wenn die Latenz wichtig ist, können Sie sich die Protokolle ansehen, um sicherzustellen, dass Ihr Pool gut genutzt wird, indem Sie nachsehen, wann urllib3 eine neue Verbindung aufbaut oder eine inaktive Verbindung schließt.

  • urllib3.connectionpool: Wird für die Protokollierung von Ereignissen verwendet, die den Verbindungspool behandeln.

Der folgende Codeausschnitt legt fest, dass der Großteil der Protokollierung die Protokollierung von Endpunkt- und INFO DEBUG Verbindungspool-Aktivitäten umfasst:

import logging logging.getLogger('boto3').setLevel(logging.INFO) logging.getLogger('botocore').setLevel(logging.INFO) logging.getLogger('botocore.endpoint').setLevel(logging.DEBUG) logging.getLogger('urllib3.connectionpool').setLevel(logging.DEBUG)

Event-Hooks

Botocore gibt während verschiedener Phasen seiner Ausführung Ereignisse aus. Sie können Handler für diese Ereignisse registrieren, sodass Ihr Handler immer dann aufgerufen wird, wenn ein Ereignis ausgelöst wird. Auf diese Weise können Sie das Verhalten von Botocore erweitern, ohne die internen Funktionen ändern zu müssen.

Nehmen wir zum Beispiel an, Sie möchten jedes Mal verfolgen, wenn ein PutItem Vorgang für eine DynamoDB-Tabelle in Ihrer Anwendung aufgerufen wird. Sie können sich für das 'provide-client-params.dynamodb.PutItem' Ereignis registrieren, um jedes Mal, wenn ein PutItem Vorgang in der zugehörigen Sitzung aufgerufen wird, abzufangen und zu protokollieren. Ein Beispiel:

import boto3 import botocore import logging def log_put_params(params, **kwargs): if 'TableName' in params and 'Item' in params: logging.info(f"PutItem on table {params['TableName']}: {params['Item']}") logging.basicConfig(level=logging.INFO) session = boto3.Session() event_system = session.events # Register our interest in hooking in when the parameters are provided to PutItem event_system.register('provide-client-params.dynamodb.PutItem', log_put_params) # Now, every time you use this session to put an item in DynamoDB, # it will log the table name and item data. dynamodb = session.resource('dynamodb') table = dynamodb.Table('YourTableName') table.put_item( Item={ 'pk': '123', 'sk': 'cart#123', 'item_data': 'YourItemData', # ... more attributes ... } )

Innerhalb des Handlers können Sie die Parameter sogar programmgesteuert bearbeiten, um das Verhalten zu ändern:

params['TableName'] = "NewTableName"

Weitere Informationen zu Ereignissen finden Sie in der botocore-Dokumentation zu Ereignissen und in der boto3-Dokumentation zu Ereignissen.

Paginierung und der Paginator

Einige Anfragen, wie Query und Scan, beschränken die Größe der Daten, die bei einer einzelnen Anfrage zurückgegeben werden, und erfordern, dass Sie wiederholte Anfragen stellen, um nachfolgende Seiten abzurufen.

Mit dem limit Parameter können Sie die maximale Anzahl von Elementen steuern, die für jede Seite gelesen werden sollen. Wenn Sie beispielsweise die letzten 10 Elemente abrufen möchten, können Sie limit damit nur die letzten 10 abrufen. Beachten Sie, dass der Grenzwert angibt, wie viel aus der Tabelle gelesen werden sollte, bevor eine Filterung angewendet wird. Es gibt keine Möglichkeit, genau 10 nach dem Filtern anzugeben. Sie können nur die Anzahl der vorgefilterten Filter kontrollieren und clientseitig überprüfen, ob Sie tatsächlich 10 abgerufen haben. Unabhängig vom Limit hat jede Antwort immer eine maximale Größe von 1 MB.

Wenn die Antwort ein enthält, bedeutet diesLastEvaluatedKey, dass die Antwort beendet wurde, weil sie eine Anzahl- oder Größenbeschränkung erreicht hat. Der Schlüssel ist der letzte Schlüssel, der für die Antwort ausgewertet wurde. Sie können dies abrufen LastEvaluatedKey und an einen Folgeaufruf weiterleitenExclusiveStartKey, um den nächsten Abschnitt von diesem Startpunkt aus zu lesen. Wenn nichts LastEvaluatedKey zurückgegeben wird, bedeutet das, dass es keine weiteren Elemente gibt, die der Abfrage oder dem Scan entsprechen.

Hier ist ein einfaches Beispiel (unter Verwendung der Resource-Schnittstelle, aber die Client-Schnittstelle hat das gleiche Muster), bei dem maximal 100 Elemente pro Seite gelesen werden und eine Schleife ausgeführt wird, bis alle Elemente gelesen wurden.

import boto3 dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('YourTableName') query_params = { 'KeyConditionExpression': Key('pk').eq('123') & Key('sk').gt(1000), 'Limit': 100 } while True: response = table.query(**query_params) # Process the items however you like for item in response['Items']: print(item) # No LastEvaluatedKey means no more items to retrieve if 'LastEvaluatedKey' not in response: break # If there are possibly more items, update the start key for the next page query_params['ExclusiveStartKey'] = response['LastEvaluatedKey']

Der Einfachheit halber kann boto3 dies mit Paginatoren für Sie erledigen. Es funktioniert jedoch nur mit der Client-Oberfläche. Hier ist der Code, der für die Verwendung von Paginatoren neu geschrieben wurde:

import boto3 dynamodb = boto3.client('dynamodb') paginator = dynamodb.get_paginator('query') query_params = { 'TableName': 'YourTableName', 'KeyConditionExpression': 'pk = :pk_val AND sk > :sk_val', 'ExpressionAttributeValues': { ':pk_val': {'S': '123'}, ':sk_val': {'N': '1000'}, }, 'Limit': 100 } page_iterator = paginator.paginate(**query_params) for page in page_iterator: # Process the items however you like for item in page['Items']: print(item)

Weitere Informationen finden Sie im Leitfaden zu Paginatoren und in der API-Referenz für DynamoDB.Paginator.Query.

Anmerkung

Paginatoren haben auch ihre eigenen Konfigurationseinstellungen mit den Namen, und. MaxItems StartingToken PageSize Für die Paginierung mit DynamoDB sollten Sie diese Einstellungen ignorieren.

Waiter

Kellner bieten die Möglichkeit, zu warten, bis etwas abgeschlossen ist, bevor Sie fortfahren. Derzeit unterstützen sie nur das Warten darauf, dass eine Tabelle erstellt oder gelöscht wird. Im Hintergrund führt der Kellnerbetrieb bis zu 25 Mal alle 20 Sekunden einen Scheck für Sie durch. Sie könnten das selbst tun, aber die Verwendung eines Kellners ist elegant, wenn es um Automatisierung geht.

Dieser Code zeigt, wie man darauf wartet, dass eine bestimmte Tabelle erstellt wurde:

# Create a table, wait until it exists, and print its ARN response = client.create_table(...) waiter = client.get_waiter('table_exists') waiter.wait(TableName='YourTableName') print('Table created:', response['TableDescription']['TableArn']

Weitere Informationen finden Sie im Leitfaden für Kellner und in der Referenz zu Kellnern.