

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
<a name="programming-with-python"></a>

Dieser Leitfaden bietet eine Einführung für Programmierer, die Amazon DynamoDB mit Python verwenden möchten. Erfahren Sie mehr über die Abstraktionsebenen, das Konfigurationsmanagement, den Umgang mit Fehlern, die Steuerung von Wiederholungsrichtlinien, die Verwaltung von Keepalive und mehr.

**Topics**
+ [Informationen zu Boto](#programming-with-python-about)
+ [Verwenden der Boto-Dokumentation](#programming-with-python-documentation)
+ [Grundlegendes zu den Abstraktionsebenen für Clients und Ressourcen](#programming-with-python-client-resource)
+ [Verwenden der Tabellenressource batch\$1writer](#programming-with-python-batch-writer)
+ [Zusätzliche Codebeispiele zur Client- und Ressourcenebene](#programming-with-python-additional-code)
+ [Verständnis der Interaktion von Client- und Resource-Objekten mit Sitzungen und Threads](#programming-with-python-sessions-thread-safety)
+ [Anpassen des Config-Objekts](#programming-with-python-config)
+ [Fehlerbehandlung](#programming-with-python-error-handling)
+ [Protokollierung](#programming-with-python-logging)
+ [Ereignis-Hooks](#programming-with-python-event-hooks)
+ [Paginierung und der Paginator](#programming-with-python-pagination)
+ [Waiter](#programming-with-python-waiters)

## Informationen zu Boto
<a name="programming-with-python-about"></a>

**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. Dieser Leitfaden 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](https://github.com/boto/botocore) und [Boto3](https://github.com/boto/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 der Boto-Dokumentation
<a name="programming-with-python-documentation"></a>

Beginnen Sie mit der Boto-Dokumentation anhand der folgenden Ressourcen:
+ Beginnen Sie mit dem [Quickstart-Abschnitt](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html), 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](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/dynamodb.html) der Dokumentation. Darin erfahren Sie, 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. Für die Beispiele wird die Schnittstelle **Ressourcen** verwendet. Wenn Sie `boto3.resource('dynamodb')` sehen, bedeutet das, dass Sie die übergeordnete Schnittstelle **Ressourcen** verwenden.
+ Nach dem Leitfaden können Sie sich die [DynamoDB-Referenz](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html) nochmals ansehen. Diese Startseite bietet eine vollständige Liste der Klassen und Methoden, die Ihnen zur Verfügung stehen. Ganz oben sehen Sie die `DynamoDB.Client`-Klasse. Diese bietet Low-Level-Zugriff auf alle Operationen auf der Steuerungsebene und der Datenebene. Schauen Sie sich ganz unten die `DynamoDB.ServiceResource`-Klasse an. 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`-Instance für tabellenspezifische Aktionen abrufen.

## Grundlegendes zu den Abstraktionsebenen für Clients und Ressourcen
<a name="programming-with-python-client-resource"></a>

Die beiden Schnittstellen, mit denen Sie arbeiten werden, sind die **Client**- und die **Ressourcen**-Schnittstelle. 
+ Die Low-Level-**Client**-Schnittstelle bietet eine Eins-zu-Eins-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 häufig ausführlicher und komplexer in der Anwendung ist.
+ Die High-Level-**Ressourcen**-Schnittstelle bietet keine 1-zu-1-Zuordnung der zugrunde liegenden Service-API. Sie bietet jedoch Methoden, die Ihnen den Zugriff auf den Service erleichtern, z. B `batch_writer`.

Hier 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 dieselbe `PutItem`-Operation, jedoch unter Verwendung der Ressourcenschnittstelle. 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 Klassen `TypeSerializer` und `TypeDeserializer` von dem normalen JSON- zum DynamoDB-JSON-Format 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. Sie drückt die Abfrage als ein JSON-Konstrukt aus. Es wird eine `KeyConditionExpression`-Zeichenfolge verwendet, 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',
    }
)
```

Dieselbe Abfrageoperation, die 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 (dabei handelt es sich um 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:

```
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](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/resources.html) keine neuen Funktionen hinzugefügt werden: „Das AWS Python SDK-Team beabsichtigt nicht, der Ressourcenschnittstelle in boto3 neue Funktionen hinzuzufügen. Vorhandene Schnittstellen werden während des Lebenszyklus von boto3 weiterhin funktionieren. Kunden können über die Client-Oberfläche auf neuere Service-Features zugreifen.“

## Verwenden der Tabellenressource batch\$1writer
<a name="programming-with-python-batch-writer"></a>

Ein Vorteil, der nur mit der High-Level-Tabellenressource 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 Netzwerkanfrage. Eine solche Batchverarbeitung verbessert die Effizienz, da Netzwerk-Roundtrips minimiert werden.

Mit der Low-Level-Client-Bibliothek verwenden Sie die `client.batch_write_item()`-Operation, um Batches auszuführen. Sie müssen Ihre Arbeit manuell in Batches 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 eine spätere `batch_write_item()`-Operation übergeben. Es gibt eine beträchtliche Menge an Boilerplate-Code.

Die Methode [Table.batch\$1writer](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/table/batch_writer.html) erstellt einen Kontextmanager zum Schreiben von Objekten in einem Batch. Dieser stellt eine Schnittstelle bereit, bei der es so aussieht, als würden Sie Elemente einzeln schreiben, aber intern werden die Elemente gepuffert und in Batches gesendet. Außerdem verarbeitet er 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 zur Client- und Ressourcenebene
<a name="programming-with-python-additional-code"></a>

Sie können auch auf die folgenden Beispiel-Repositorys verweisen, die die Nutzung verschiedener Funktionen sowohl mit dem Client als auch mit der Ressourcenebene untersuchen:
+ [Offizielle AWS -Single-Action-Codebeispiele](https://docs.aws.amazon.com/code-library/latest/ug/python_3_dynamodb_code_examples.html) 
+ [Offizielle AWS szenarioorientierte Codebeispiele.](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/python)
+ [Von der Community verwaltete Beispiele für Single-Action-Codes](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/python)

## Verständnis der Interaktion von Client- und Resource-Objekten mit Sitzungen und Threads
<a name="programming-with-python-sessions-thread-safety"></a>

Das Resource-Objekt ist nicht Thread-sicher und sollte nicht über Threads oder Prozesse hinweg gemeinsam genutzt werden. Weitere Informationen finden Sie im [Leitfaden zur Resource](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/resources.html#multithreading-or-multiprocessing-with-resources).

Das Client-Objekt hingegen ist im Allgemeinen Thread-sicher. Ausgenommen sind bestimmte fortgeschrittene Features. Weitere Informationen finden Sie im [Leitfaden zu Clients](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/clients.html#multithreading-or-multiprocessing-with-clients). 

Das Sitzungsobjekt ist nicht Thread-sicher. Daher sollten Sie in einer Multi-Threading-Umgebung für jeden neuen Client oder jedes neue Ressourcenobjekt zunächst eine neue Sitzung erstellen und daraus dann den jeweiligen Client oder das Ressourcenobjekt ableiten. Weitere Informationen finden Sie im [Leitfaden zu Sitzungen](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/session.html#multithreading-or-multiprocessing-with-sessions). 

Wenn Sie `boto3.resource()` aufrufen, verwenden Sie implizit die Standardsitzung. Das ist praktisch für das Schreiben von Single-Threaded-Code. Für Multi-Threaded-Code sollten Sie hingegen für jeden Thread eine eigene Session erstellen und daraus die jeweilige Resource abrufen:

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

## Anpassen des Config-Objekts
<a name="programming-with-python-config"></a>

Beim Erstellen eines Client- oder Resource-Objekts können Sie optionale benannte Parameter übergeben, um das Verhalten zu steuern. Der Parameter `config` schaltet dabei eine Vielzahl von Funktionen frei. Es handelt sich um eine Instance von `botocore.client.Config`, und die [Referenzdokumentation zu Config](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html) zeigt alle verfügbaren Optionen zur Steuerung. Die [Anleitung zur Konfiguration](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html) 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 Anwendung einer benutzerdefinierten Konfiguration besteht darin, das Netzwerkverhalten anzupassen:
+ **connect\$1timeout (float oder int)** – Die Zeit in Sekunden, bis eine Timeout-Ausnahme beim Versuch eines Verbindungsaufbaus ausgelöst wird. Standardmäßig ist ein Zeitraum von 60 Sekunden festgelegt.
+ **read\$1timeout (float oder int)** – Die Zeit in Sekunden, bis beim Versuch einer Verbindungslesung 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 eine vorübergehende Netzwerkstörung eine Verzögerung von einer Minute verursacht, bevor der Client einen erneuten Versuch unternehmen 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](https://aws.amazon.com/blogs/database/tuning-aws-java-sdk-http-request-settings-for-latency-aware-amazon-dynamodb-applications/) DynamoDB-Anwendungen. Beachten Sie, dass das Java-SDK mehr Timeout-Konfigurationsmöglichkeiten bietet als das Python-SDK.

**Config für Keepalive**

Wenn Sie Botocore 1.27.84 oder höher verwenden, können Sie auch **TCP Keepalive** steuern:
+ **tcp\$1keepalive** (bool) – Aktiviert die Socket-Option TCP-Keepalive beim Erstellen neuer Verbindungen, wenn diese auf `True` gesetzt wurde (Standard ist `False`). Dies ist nur ab Botocore 1.27.84 verfügbar.

Wenn Sie TCP Keepalive auf `True` setzen, können Sie die durchschnittlichen Latenzen reduzieren. Hier ein Beispielcode, der TCP Keepalive 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 Keepalive unterscheidet sich von HTTP Keepalive. Bei TCP Keepalive werden kleine Pakete vom zugrunde liegenden Betriebssystem über die Socket-Verbindung gesendet, um die Verbindung aufrechtzuerhalten und etwaige Unterbrechungen sofort zu erkennen. Mit HTTP Keepalive wird die auf dem zugrunde liegenden Socket aufgebaute Webverbindung wiederverwendet. HTTP Keepalive ist bei boto3 immer aktiviert.

Es gibt jedoch eine Begrenzung, wie lange eine inaktive Verbindung aufrechterhalten werden kann. Erwägen Sie, regelmäßige Anfragen zu senden (z. B. jede Minute), wenn Sie eine Leerlaufverbindung haben, aber möchten, dass die nächste Anfrage eine bereits bestehende Verbindung nutzt.

**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 der Wiederholungsversuch schließlich erfolgreich ist), wird aus Sicht des aufrufenden Codes kein Fehler sichtbar, sondern nur eine leicht erhöhte Latenz. Hier sind die Werte, die Sie angeben können:
+ **max\$1attempts** – 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 weiteren Wiederholungsversuche durchgeführt. 
+ **total\$1max\$1attempts** – 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 weiteren Anfragen versucht werden. Wenn sowohl `total_max_attempts` als auch `max_attempts` angegeben sind, hat `total_max_attempts` Vorrang. `total_max_attempts` und nicht `max_attempts` wird bevorzugt, da er mit der Umgebungsvariable `AWS_MAX_ATTEMPTS` und dem Konfigurationswert `max_attempts` in der Konfigurationsdatei übereinstimmt.
+ **mode** – Eine Zeichenfolge, die den Typ des Wiederholungsmodus darstellt, den Botocore verwenden soll. Gültige Werte sind:
  + **legacy** – Der Standardmodus. Wartet 50 ms beim ersten Wiederholungsversuch und verwendet dann ein exponentielles Backoff mit dem Basisfaktor 2. Für DynamoDB sind es insgesamt maximal 10 Versuche (sofern nicht wie oben gezeigt überschrieben wurde).
**Anmerkung**  
Bei exponentiellem Backoff wird fast 13 Sekunden mit dem letzten Versuch gewartet.
  + **Standard — Wird** als Standard bezeichnet, weil er konsistenter mit anderen ist. AWS SDKs Beim ersten Wiederholungsversuch wird eine zufällige Zeitspanne zwischen 0 ms und 1 000 ms abgewartet. Sollte ein weiterer Versuch erforderlich sein, wird erneut ein zufälliger Zeitraum zwischen 0 ms und 1 000 ms gewählt und mit 2 multipliziert. Sollten weitere Wiederholungsversuche erforderlich sein, erfolgt dieselbe zufällige Auswahl, multipliziert mit 4 usw. Jede Wartezeit ist auf 20 Sekunden begrenzt. Dieser Modus führt mehr Wiederholungen für mehr erkannte Fehlerbedingungen aus als der `legacy`-Modus. Für DynamoDB sind es insgesamt maximal 3 Versuche (sofern nicht wie oben gezeigt überschrieben wurde). 
  + **adaptive** - Ein experimenteller Wiederholungsmodus, der alle Funktionalitäten des Standardmodus beinhaltet, aber eine automatische clientseitige Drosselung hinzufügt. Mit adaptiver Ratenbegrenzung SDKs kann die Geschwindigkeit, mit der Anfragen gesendet werden, verlangsamt werden, um der Kapazität der AWS Dienste besser gerecht zu werden. Dies ist ein vorläufiger Modus, dessen Verhalten sich ändern kann. 

Eine erweiterte Definition dieser Wiederholungsmodi finden Sie in der [Anleitung zu Wiederholungsversuchen](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/retries.html) sowie im [Thema Wiederholungsverhalten in der SDK-Referenz](https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html).

Hier 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 `ProvisionedThroughputExceededException` oder `ThrottlingException`) weist auf einen fehlerfreien Service 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 Backoff erforderlich, da Drosselungen für DynamoDB leichtgewichtig sind und keine Gebühren pro Anfrage anfallen. Exponentielles Backoff weist längere Wartezeiten jenen Client-Threads zu, die bereits am längsten gewartet haben, wodurch sich die statistischen Kennzahlen p50 und p99 weiter nach außen verschieben.
+ Ein **Fehler** (unter anderem durch `InternalServerError` oder `ServiceUnavailable` gekennzeichnet) weist auf ein vorübergehendes Problem mit dem Service hin. Dies kann für die gesamte Tabelle oder möglicherweise nur für die Partition gelten, aus der Sie lesen oder in die Sie schreiben. Bei Fehlern sollten Sie längere Pausen zwischen den Wiederholungsversuchen einlegen (etwa 250 ms oder 500 ms) und Jitter verwenden, um die Wiederholungen zeitlich zu staffeln.

**Config für maximale Poolverbindungen**

Abschließend ermöglicht die Konfiguration die Steuerung der Größe des Verbindungs-Pools:
+ **max\$1pool\$1connections (int)** – Die maximale Anzahl von Verbindungen, die in einem Verbindungspool beibehalten werden sollen. Wenn kein Wert festgelegt ist, wird der Standardwert 10 verwendet.

Diese Option steuert die maximale Anzahl von HTTP-Verbindungen, die zur Wiederverwendung gepoolt werden sollen. Für jede Sitzung wird ein anderer Pool verwaltet. Wenn Sie erwarten, dass mehr als 10 Threads gleichzeitig auf Clients oder Ressourcen zugreifen, die aus derselben Sitzung erstellt wurden, sollten Sie diesen Wert erhöhen, damit Threads nicht auf andere Threads warten müssen, die gerade eine gepoolte Verbindung 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
<a name="programming-with-python-error-handling"></a>

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 Service-Ausnahmen als `ClientError` und stellt die Details als strukturiertes JSON bereit. Ein Fehlerantwort könnte beispielsweise wie folgt aufgebaut 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 prüft den Zeichenfolgenwert des `Code` innerhalb des `Error`, um zu bestimmen, welche Aktion ausgeführt werden soll:

```
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 Top-Level-Klassen materialisiert. Sie können diese direkt behandeln. Wenn Sie die Client-Schnittstelle verwenden, werden diese Ausnahmen dynamisch in Ihrem Client-Objekt bereitgestellt, und Sie fangen sie über Ihre Client-Instance ab:

```
except ddb_client.exceptions.ProvisionedThroughputExceededException:
```

Wenn Sie die Ressourcenschnittstelle verwenden, müssen Sie `.meta.client` nutzen, um vom Ressourcenobjekt zum zugrunde liegenden Client zu gelangen und auf die Ausnahmen zuzugreifen:

```
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 eine Schreiboperation mit einem Bedingungsausdruck ausführen, können Sie vorgeben, 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](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/error-handling.html) enthält weitere Informationen über Methoden zur Fehlerbehandlung. 
+ Im [DynamoDB-Entwicklerhandbuch zu Programmierfehlern](Programming.Errors.md) ist aufgeführt, auf welche Fehler Sie stoßen könnten. 
+ Der [Abschnitt Häufige Fehler in der API-Referenz](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/CommonErrors.html).
+ In der Dokumentation zu den einzelnen API-Vorgängen ist aufgeführt, welche Fehler dieser Aufruf erzeugen könnte (zum Beispiel [BatchWriteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html)).

## Protokollierung
<a name="programming-with-python-logging"></a>

Die Boto3-Bibliothek integriert sich mit dem in Python eingebauten Protokollierungsmodul, um Vorgänge während einer Sitzung zu protokollieren. Sie können das Protokollierungsmodul konfigurieren, um die Protokollierungsebenen zu steuern:

```
import logging

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

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

Die Logger in boto3 sind hierarchisch aufgebaut. Die Bibliothek verwendet verschiedene Logger, die jeweils unterschiedlichen Teilen der Bibliothek entsprechen. Sie können das Verhalten der einzelnen Logger separat steuern:
+ **boto3**: Der Hauptlogger für das boto3-Modul.
+ **botocore**: Der Hauptlogger für das Botocore-Paket.
+ **botocore.auth**: Wird zum Protokollieren der AWS -Signaturerstellung für Anfragen verwendet.
+ **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 für die Protokollierung verwendet, wenn Teile von AWS Servicemodellen geladen werden.
+ **botocore.parsers**: Wird zum Protokollieren von AWS -Serviceantworten verwendet, bevor sie geparst werden.
+ **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 Ihnen Latenz wichtig ist, können Sie sich die Protokolle ansehen, um sicherzustellen, dass Ihr Pool gut ausgelastet ist, indem Sie nachsehen, wann urllib3 eine neue Verbindung aufbaut oder eine inaktive Verbindung schließt.
+ **urllib3.connectionpool**: Wird für die Protokollierung von Ereignissen bei der Verwaltung des Verbindungspools verwendet.

Der folgende Codeausschnitt setzt die allgemeine Protokollierung auf `INFO`, während für Endpunkt- und Verbindungspoolaktivitäten die `DEBUG`-Protokollierung aktiviert wird:

```
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)
```

## Ereignis-Hooks
<a name="programming-with-python-event-hooks"></a>

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.

Angenommen, Sie möchten jedes Mal nachverfolgen, wenn in Ihrer Anwendung eine `PutItem`-Operation auf einer beliebigen DynamoDB-Tabelle ausgeführt wird. Dann könnten Sie sich auf das Ereignis `'provide-client-params.dynamodb.PutItem'` registrieren, um jeden Aufruf von `PutItem` innerhalb der zugehörigen Sitzung zu erfassen und zu protokollieren. Hier 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 programmatisch verändern, um das Verhalten anzupassen:

```
params['TableName'] = "NewTableName"
```

Weitere Informationen zu Ereignissen finden Sie in der [Botocore-Dokumentation zu Ereignissen](https://botocore.amazonaws.com/v1/documentation/api/latest/topics/events.html) und in der [boto3-Dokumentation zu Ereignissen](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/events.html).

## Paginierung und der Paginator
<a name="programming-with-python-pagination"></a>

Manche Anfragen wie Query und Scan begrenzen die Datenmenge, die mit einer einzelnen Anfrage zurückgegeben wird, und erfordern wiederholte Anfragen, um nachfolgende Seiten abzurufen.

Mit dem `limit`-Parameter können Sie die maximale Anzahl von Elementen steuern, die pro Seite gelesen werden sollen. Beispielsweise können Sie `limit` verwenden, um nur die letzten 10 Elemente abzurufen. 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 Grenzwert hat jede Antwort immer eine maximale Größe von 1 MB.

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

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

```
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. Das funktioniert jedoch nur mit der Client-Schnittstelle. 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](https://botocore.amazonaws.com/v1/documentation/api/latest/topics/events.html) und in der [API-Referenz für DynamoDB.Paginator.Query](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/paginator/Query.html).

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

## Waiter
<a name="programming-with-python-waiters"></a>

Waiter bieten die Möglichkeit, auf den Abschluss eines Vorgangs zu warten, bevor der nächste Schritt ausgeführt wird. Derzeit unterstützen sie nur das Warten auf die Erstellung oder Löschung einer Tabelle. Im Hintergrund prüft der Waiter alle 20 Sekunden, bis zu 25 Mal, ob der gewünschte Zustand erreicht wurde. Zwar könnten Sie diese Prüfung selbst implementieren, aber die Verwendung eines Waiters ist eine elegante Lösung beim Schreiben von Automatisierungsskripten.

Hier ist ein Beispielcode, der zeigt, wie Sie darauf warten können, 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 [Waiter-Leitfaden](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/clients.html#waiters) und in der [Waiter-Referenz](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#waiters).