How can I store 30.40 in DynamoDb?
See original GitHub issueIt’s the end of the day, maybe i’m not seeing this clearly… But I am unable to store simple float values without adding some arcane magic to the mix.
Using .put_item on a Table resource that contains a float:
item = {'name': 'testing_row', 'foo': 30.40}
table.put_item(Item=item)
>> TypeError: Float types are not supported. Use Decimal types instead.
The same thing, using Decimal:
item = {'name': 'testing_row', 'foo': Decimal(30.40)}
table.put_item(Item=item)
>> Inexact: None
This last one should have gone through, no? The stack trace is this:
> table.put_item(Item=item)
E:\Projects\Repos\tests\test_dynamodb.py:9:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\Python27\lib\site-packages\boto3\resources\factory.py:518: in do_action
response = action(self, *args, **kwargs)
C:\Python27\lib\site-packages\boto3\resources\action.py:83: in __call__
response = getattr(parent.meta.client, operation_name)(**params)
C:\Python27\lib\site-packages\botocore\client.py:258: in _api_call
return self._make_api_call(operation_name, kwargs)
C:\Python27\lib\site-packages\botocore\client.py:524: in _make_api_call
api_params, operation_model, context=request_context)
C:\Python27\lib\site-packages\botocore\client.py:574: in _convert_to_request_dict
params=api_params, model=operation_model, context=context)
C:\Python27\lib\site-packages\botocore\hooks.py:227: in emit
return self._emit(event_name, kwargs)
C:\Python27\lib\site-packages\botocore\hooks.py:210: in _emit
response = handler(**kwargs)
C:\Python27\lib\site-packages\boto3\dynamodb\transform.py:197: in inject_attribute_value_input
'AttributeValue')
C:\Python27\lib\site-packages\boto3\dynamodb\transform.py:252: in transform
model, params, transformation, target_shape)
C:\Python27\lib\site-packages\boto3\dynamodb\transform.py:259: in _transform_parameters
model, params, transformation, target_shape)
C:\Python27\lib\site-packages\boto3\dynamodb\transform.py:274: in _transform_structure
target_shape)
C:\Python27\lib\site-packages\boto3\dynamodb\transform.py:259: in _transform_parameters
model, params, transformation, target_shape)
C:\Python27\lib\site-packages\boto3\dynamodb\transform.py:283: in _transform_map
params[key] = transformation(value)
C:\Python27\lib\site-packages\boto3\dynamodb\types.py:103: in serialize
return {dynamodb_type: serializer(value)}
C:\Python27\lib\site-packages\boto3\dynamodb\types.py:204: in _serialize_n
number = str(DYNAMODB_CONTEXT.create_decimal(value))
C:\Python27\lib\decimal.py:3938: in create_decimal
return d._fix(self)
C:\Python27\lib\decimal.py:1712: in _fix
context._raise_error(Inexact)
I can make it go through if I use the string trick in the Decimal constructor:
item = {'name': 'testing_row', 'foo': Decimal('30.40')}
table.put_item(Item=item)
Having done that, using AWS’s dashboard to look into the table, I can see a number type with the value of 30.4 but then I cannot assert its value in my tests:
item = table.get_item(Key={'name': 'testing_row'})['Item']['foo']
assert item == 30.4
>> False
This seems to work:
assert float(item) == 30.4
So how’s this supposed to work exactly? Is it expected that I must 1) provide a string to decimal and 2) convert back to float myself for equality to work properly?
Issue Analytics
- State:
- Created 7 years ago
- Reactions:59
- Comments:24 (4 by maintainers)
Top Results From Across the Web
Best practices for storing large items and attributes
Compressing large attribute values can let them fit within item limits in DynamoDB and reduce your storage costs. Compression algorithms such as GZIP...
Read more >github dynamodb float types are not supported convert to ...
Convert Float to Decimal Data Types for Boto3 DynamoDB Using Python . ... boto/boto3How can I store 30.40 in DynamoDb?#665. Created over 6...
Read more >AWS re:Invent 2018: Amazon DynamoDB Deep Dive - YouTube
This session is for those who already have some familiarity with DynamoDB. The patterns and data models discussed in this session summarize ...
Read more >DynamoDB Crud Examples With Boto3 and Python
In this example, we want all users with the last name of Johnson that fall in the age range of 30-40. Note the...
Read more >How to save json data as it is without data type conversion in ...
What you see stored is DynamoDB JSON and all data is stored in DynamoDB that way. When you read the item back using...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@kyleknap did you look at the example I provided after the stack trace, in my original post?
I don’t agree with this behavior being normal. Having to wrap these calls with home-made recursive conversion functions goes against the principle that you can usually just pass a boto resource around. It should be usable as-is.
I understand that python floats are annoying and unprecise, but boto really should handle the extra step of handling these conversions for the user. I agree that it shouldn’t allow Inexact conversions, but for this it would be better to allow the user to attach his own conversion function when Inexact is raised.
@kyleknap
Any progress on this?
It’s mind boggling how boto doesn’t allow floats (python’s default floating type) out of the box. The most trivial put_item call raises this issue, not to mention the pain of using decimals with json.dumps and json.loads.