Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python and DynamoDB decimal.Inexact

I am trying to delete an item from my dynamodb Table, however I get this exception:

decimal.Inexact: [<class 'decimal.Inexact'>, <class 'decimal.Rounded'>]

I have no idea how to fix it though, any help? This is the code:

dynamodb = boto3.resource('dynamodb', region_name='***')

table = dynamodb.Table('***')

propid = 1234
column_set = Decimal(44.30912302164986)

print("Attempting a conditional delete...")

try:
    response = table.delete_item(
        Key={
            'hashkey': propid,
            'rangekey': column_set
        },
    )
except ClientError as e:
    if e.response['Error']['Code'] == "ConditionalCheckFailedException":
        print(e.response['Error']['Message'])
    else:
        raise
else:
    print("DeleteItem succeeded:")

Later edit:

It seems that it doesn't store properly, when I do this:

year = decimal.Decimal(44.309123021649860)

It prints:

44.30912302164986016350667341612279415130615234375
like image 420
Barkz Avatar asked Apr 03 '18 15:04

Barkz


2 Answers

I don't know why this is happening, but for what it's worth, you can do something like the following (based on this comment found in boto3 issue thread):

with decimal.localcontext(boto3.dynamodb.types.DYNAMODB_CONTEXT) as ctx:
    ctx.traps[decimal.Inexact] = False
    ctx.traps[decimal.Rounded] = False
    column_set = ctx.create_decimal_from_float(v)

    response = table.delete_item(
        Key={
            'hashkey': propid,
            'rangekey': column_set
        },
    )
like image 53
Milan Cermak Avatar answered Oct 15 '22 04:10

Milan Cermak


I have a Float to Decimal function that recursively iterates through my nested dict from the original JSON payload and converts all Floats to Decimals and then round the result, which works for me. I then put_item this to DynamoDB without issues.

def ConvertFloatToDecimal(d):

for k, v in d.items():
    if isinstance(v, float):
        d[k] = round(decimal.Decimal(v), 4)
    elif isinstance(v, dict):
        ConvertFloatToDecimal(v)
    elif isinstance(v, list):
        for i in v:
            if isinstance(i, dict):
                ConvertFloatToDecimal(i)
            elif isinstance(i, float):
                v[i] = round(decimal.Decimal(i), 4)
like image 27
Kurt Heiz Avatar answered Oct 15 '22 04:10

Kurt Heiz