Python'da (boto3) DynamoDB PutItem

put_item, bir öğenin tamamını yazar ve aynı birincil anahtara sahip mevcut her öğenin yerini alır (öğe tabanlı eylemler bunun update_item'dan nasıl ayrıldığını ele alıyor). Düşük düzeyli istemcide her öznitelik DynamoDB JSON olarak geçilir ve boto3, hiçbir şey gönderilmeden önce bu biçimi yerel olarak denetler.

Kod

import boto3
from botocore.exceptions import ClientError

client = boto3.client("dynamodb")

try:
    client.put_item(
        TableName="Music",
        Item={"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}, "AlbumTitle": {"S": "Danzon"}, "Year": {"N": "1994"}, "Awards": {"N": "0"}},
        ConditionExpression="attribute_not_exists(#cond0) AND attribute_not_exists(#cond1)",
        ExpressionAttributeNames={"#cond0": "Artist", "#cond1": "SongTitle"},
    )
    print("Song written")
except ClientError as err:
    if err.response["Error"]["Code"] == "ConditionalCheckFailedException":
        print("A song with that key already exists — not overwritten")
    else:
        raise

Açıklama

{"N": 1994} hiçbir zaman AWS'ye ulaşmaz ve except ClientError onu yakalamaz. Botocore isteği önce kendi hizmet modeline karşı doğrular ve N türünün dize beklediği yerdeki bir Python int'i orada başarısız olur:

ParamValidationError: Parameter validation failed:
Invalid type for parameter Item.Year.N, value: 1994, type: <class 'int'>, valid types: <class 'str'>

ParamValidationError, ClientError'dan değil BotoCoreError'dan türer; dolayısıyla yukarıdaki parçacıktaki işleyici onu geçirir. Genellikle istediğiniz de budur, çünkü bu bir iş sonucu değil bir hatadır; ama bir yazmanın etrafındaki try/except ClientError'ın her şeyi yakalamadığı anlamına gelir. İyi yanı, hatanın tam yolu, Item.Year.N, adlandırmasıdır; hata ayıklamada bu, sunucu tarafı bir ValidationException'ı yener. Ayrıntı "Parameter validation failed" sayfasında.

Başarısız bir koşulun tüm yüzeyi. Aynı koşullu put'u iki kez yakalayıp istisnadaki her şeyi yazdırmak şunu verdi:

type(e).__name__                              ConditionalCheckFailedException
e.response["Error"]["Code"]                   ConditionalCheckFailedException
e.response["Error"]["Message"]                The conditional request failed
e.response["ResponseMetadata"]["HTTPStatusCode"]  400
str(e)                                        An error occurred (ConditionalCheckFailedException) when calling the PutItem operation: The conditional request failed

Bundan iki şey çıkar. botocore 1.43.58'de nesne modellenmiş bir alt sınıftır, dolayısıyla except client.exceptions.ConditionalCheckFailedException, parçacığın kullandığı err.response["Error"]["Code"] kontrolüyle yan yana çalışır; birini seçin ve tutarlı olun. Ve str(e) hizmetin mesajı değil biçimlendirilmiş bir cümledir, dolayısıyla onu asla bir sabitle karşılaştırmayın.

Başarısız bir koşul yine de bir yazma faturalandırır. AWS: "if the expression evaluates to false, DynamoDB still consumes write capacity units from the table" (2026-07-28 tarihinde alındı). Yalnızca-oluştur yeniden deneme döngüsü, reddedilen her denemenin bedelini öder. Ölçek için: ~15 KB'lık bir öğenin başarılı bir put'u, ReturnConsumedCapacity="TOTAL" altında "CapacityUnits": 15 bildirdi; yazmalar, okumaların kullandığı 4 KB'a değil, 1 KB başına yuvarlanır.

Kaynak API'si farklı bir sözleşmedir ve bunu float ile öğrenirsiniz. boto3.resource("dynamodb").Table("Music").put_item(Item={...}) düz Python alır ve marshalling'i sizin için yapar, ama ikili kayan noktayı doğrudan reddeder:

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

Değeri bir float'tan değil bir dizeden decimal.Decimal("4.5") içine sarın; yoksa hassasiyet kaybı Decimal onu görmeden önce çoktan pişmiş olur. Aynı API üzerinden geri okumak her sayıyı Decimal olarak döndürür; bu bir biçimlendirme ayrıntısı değil, kodunuzda gerçek bir değişikliktir. Bkz. "Float types are not supported".

İki API'yi karıştırmak, hiçbirinin uyarmadığı tuzaktır. Düşük düzeyli istemci, kaynak API'sinin bir float olarak reddedeceği {"N": "1.5"}'i seve seve kabul eder. Biriyle yazıp diğeriyle okuyan bir kod tabanı, girişte hiç Decimal'dan geçmemiş veriden Decimal geri alır.

#cond0 takma adları süs değildir. Bunlar ExpressionAttributeNames üzerinden Artist/SongTitle'a çözümlenir. Satır içi öznitelik adları, biri bir ayrılmış sözcükle çakışana kadar çalışır; sonra ifade, hiç değiştirmediğiniz bir ad yüzünden başarısız olur.

Görsel olarak yapın

Elle yazmanın ilk bozulduğu yer koşul ifadeleridir, çünkü yanlış olanı bir sözdizimi hatası olarak değil reddedilmiş bir yazma olarak başarısız olur. Ücretsiz DynamoDB Expression Builder, ConditionExpression'ı ad ve değer eşlemeleriyle birlikte kurar ve boto3 çağrısını yapıştırmaya hazır olarak üretir.

Kendi tablolarınıza karşı öğe yazmak ve düzenlemek — öznitelik başına bir form, tür seçiciler, sonucu boto3 olarak geri kopyalama — için DynoTable'ı indirin.

İlgili kılavuzlar

Kaynaklar

2026-07-28 tarihinde boto3 1.43.58 / botocore 1.43.58 ile 9000 numaralı bağlantı noktasındaki DynamoDB Local'a (amazon/dynamodb-local) karşı yeniden üretildi. İstisna metni, yanıt alanları ve kapasite okuması yakalanan çıktıdır, birebir kopyalanmıştır.

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.