Python (boto3) ile DynamoDB Koşullu Yazma

boto3, koşullu bir yazmanın yakalanacak adlandırılmış bir istisna sınıfına sahip olduğu tek SDK'dır ve döndürülen öğenin tahmin edemeyeceğiniz bir yerde saklandığı SDK da odur. İfadenin kendisi her yerde aynı çalışır; DynamoDB koşul ifadeleri işlevleri ve iyimser kilitleme desenini anlatır.

Kod

import boto3

client = boto3.client("dynamodb")

# Update the item only if nobody changed it since we read version 7.
try:
    client.update_item(
        TableName="Music",
        Key={"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}},
        UpdateExpression="SET #upd0 = :updValue0, #version = :newVersion",
        ConditionExpression="attribute_exists(#cond0) AND #version = :expectedVersion",
        ExpressionAttributeNames={"#upd0": "Genre", "#version": "Version", "#cond0": "Artist"},
        ExpressionAttributeValues={
            ":updValue0": {"S": "Latin Jazz"},
            ":expectedVersion": {"N": "7"},
            ":newVersion": {"N": "8"},
        },
        ReturnValuesOnConditionCheckFailure="ALL_OLD",
    )
    print("Updated to version 8")
except client.exceptions.ConditionalCheckFailedException as e:
    # With ReturnValuesOnConditionCheckFailure="ALL_OLD", the current item
    # rides back on the exception — no extra read to see what beat you.
    print("Lost the race — item is now:", e.response.get("Item"))

Açıklama

  • ConditionalCheckFailedException modellenmiş bir sınıftır, dolayısıyla except client.exceptions.… çalışır. DynamoDB hatalarının çoğu öyle değildir: ValidationException'ın hiç sınıfı yoktur ve e.response["Error"]["Code"] üzerinden eşleştirilmesi gerekir. Modellenmiş sınıf yine de ClientError'ın alt sınıfıdır, dolayısıyla üst tarafta geniş bir except ClientError, işleyicilerinizi dikkatsizce sıralarsanız onu yutar.
  • Döndürülen öğe, e.response["Error"]'ın değil, e.response'un üst düzey bir anahtarıdır. Bloğun e.response.get("Item") okumasının nedeni budur. ["Error"] altında, Code ve Message yanında aramaya gidip hiçbir şey bulamamak ve parametrenin çalışmadığı sonucuna varmak kolaydır.
  • Öğe, DynamoDB JSON olarak geri gelir — yerel değerlere alışkın olsanız bile, çünkü bu düşük düzeyli istemcidir. Düz Python isterseniz boto3.dynamodb.types.TypeDeserializer onu dönüştürür.
  • Kaynak API aynı korumayı nesnelerle ifade eder: ConditionExpression=Attr("Version").eq(7) & Attr("Artist").exists(), yerel değerlerle ve yer tutucu haritaları olmadan. Aynı istisnayı fırlatır, dolayısıyla aşağıdaki işleme değişmez.
  • Başarısız bir denetim yine de bir yazma faturalandırır. Geliştirici Kılavuzu, yanlış bir koşulun yazma kapasitesi tükettiğini ve boyutun eski ve yeni öğenin büyük olanına göre hesaplandığını açıkça belirtir; dolayısıyla çekişmeli bir anahtarda sınırsız bir yeniden deneme, hiç ilerleme kaydetmeden gerçek para harcar.

boto3 döndürülen öğeyi nereye koyar

Bloğu, depolanmış Version değeri 9 olan bir öğeye karşı çalıştırın ve istisnanın yanıt anahtarlarını yazdırın. DynamoDB Local 3.3.0, boto3 1.43.58:

sorted(e.response.keys())  ->  ['Error', 'Item', 'ResponseMetadata']

e.response["Item"]  ->  {'Artist': {'S': 'Arturo Sandoval'},
                         'Year': {'N': '1994'},
                         'Version': {'N': '9'},
                         'SongTitle': {'S': 'Cubano Chant'},
                         'AlbumTitle': {'S': 'Danzon'}}

ReturnValuesOnConditionCheckFailure'ı kaldırın; aynı başarısızlık ['Error', 'ResponseMetadata'] verir. Item anahtarı yoktur ve e.response.get("Item") bir hata fırlatmak yerine None döndürür. Bu hatanın kod incelemesinden sağ çıkan ve üretimde None günlüklemeye başlayan sürümü işte budur.

İfadedeki her ad neden takma adlandırılır

Blok, Version ve Artist yerine #version ve #cond0 yazar; bu, iki sıradan sözcük için aşırıya kaçmış görünür. Bu ikisi için öyledir. Version bir DynamoDB ayrılmış sözcüğü değildir ve çıplak kullanıldığında ad doğrulamasından geçer.

Year ise ayrılmıştır ve aynı tabloda bir tane vardır. Doğrudan onun üzerinde koruma kurarsanız şunu alırsınız:

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

O listede Name, Status, Size, Count, Data, Owner, Timestamp ve Items dahil 573 sözcük var. Her şeye takma ad vermek, üretilen kodun hangisinin hangisi olduğunu asla bilmek zorunda kalmama yöntemidir. Öznitelik adlarınızı ayrılmış sözcük denetleyicisine yapıştırın; ihtiyaç duyanlar için ExpressionAttributeNames haritasını döndürsün.

Bu korumaları takma adlandırma sizin yerinize halledilmiş hâlde kendi tablolarınıza karşı yazmak için DynoTable'ı indirin.

İlgili örnekler

Kaynaklar

En son 2026-07-28 tarihinde yukarıda bağlantısı verilen resmi AWS belgelerine karşı doğrulandı.

Console olmadan DynamoDB ile çalış

DynamoDB’nin çalıştıramadığı gerçek SQL’i çalıştıran hızlı bir DynamoDB masaüstü istemcisi — JOINs, GROUP BY, toplamalar — görsel düzenleme ve kendi Bedrock anahtarların üzerinde bir yapay zekâ aracısıyla.

30 günlük ücretsiz deneme, kredi kartı yok — ardından süre sınırı olmayan Ücretsiz plan.