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.
Themen
- Über Boto
- Verwenden Sie die Boto-Dokumentation
- Grundlegendes zu den Client- und Ressourcenabstraktionsebenen
- Verwenden Sie die Tabellenressource batch_writer
- Zusätzliche Codebeispiele, die die Client- und Ressourcenebene untersuchen
- Verstehen, wie die Client- und Resource-Objekte mit Sitzungen und Threads interagieren
- Anpassen des Config-Objekts
- Fehlerbehandlung
- Protokollierung
- Event-Hooks
- Paginierung und der Paginator
- Waiter
Ü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 eineDynamoDB.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
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
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
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
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 bereitgestelltmax_attempts
werden, hat diestotal_max_attempts
Vorrang.total_max_attempts
wird vorgezogenmax_attempts
, weil es derAWS_MAX_ATTEMPTS
Umgebungsvariablen und dem Wert dermax_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
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 einServiceUnavailable
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:
-
Der boto3-Leitfaden zur Fehlerbehandlung
enthält weitere Informationen zu Techniken zur Fehlerbehandlung. -
Im DynamoDB-Entwicklerhandbuch zu Programmierfehlern ist aufgeführt, auf welche Fehler Sie stoßen könnten.
-
In der Dokumentation zu den einzelnen API-Vorgängen ist aufgeführt, welche Fehler dieser Aufruf erzeugen könnte (zum Beispiel BatchWriteItem).
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
INFO
WARNING
,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