My code looks like below:
try:
cust_table.put_item(Item=company,
ConditionExpression=Attr('version').eq(previous_version))
except botocore.errorfactory.ConditionalCheckFailedException as ex:
print(ex)
I'm getting this error
# botocore.errorfactory.ConditionalCheckFailedException: An error occurred (ConditionalCheckFailedException) when calling the PutItem operation: The conditional request failed
# During handling of the above exception, another exception occurred:
# Traceback (most recent call last):
# File "/home/ganesh/code/vantage-trials-site-reassignment-service/createUser/src/test.py", line 45, in <module>
# except botocore.errorfactory.ConditionalCheckFailedException as ex:
# AttributeError: module 'botocore.errorfactory' has no attribute 'ConditionalCheckFailedException'
What exception to catch?
@ghsatpute - Thank you for your post. You can use botocore ClientError to catch the exceptions. Something like this:
import boto3
from botocore.exceptions import ClientError
try:
conditionalUpdateResponse = table.put_item(Item={'test':'testing20'},ConditionExpression='attribute_exists(test)')
except ClientError as e:
if e.response['Error']['Code']=='ConditionalCheckFailedException':
print(e.response['Error'])
Hope it helps.
I have done it that way.
But isn't it non-intuitive? We're not able to catch the exception that the code is raising?
I have done it that way.
But isn't it non-intuitive? We're not able to catch the exception that the code is raising?
Unfortunately we don't have very good documentation about how to catch ClientError. Here you are talking about which exception ? I believe with the above code you would be able to catch the exceptions. Can you please provide me the exact exception what your code is raising ?
So as per my experience with programming. We catch exceptions which have been raised or their parent. For example, if a code raises FileNotFoundException we catch FileNotFoundException or it's parent IOException if you don't want to differentiate between types of exception.
Here, the code is raising ConditionalCheckFailedException, I should be able to catch the same exception. Here we are catching some other exception and writing logic inside to check whether it's a part of the exception.
Obviously, this functionally works, but the working code is not everything.
@swetashre We're not catching ConditionalCheckFailedException, we're catching ClientError, there is a difference. See the line
except ClientError as e
As I said earlier, this is functionally working but it's not about that. Not all functionally working code is a good code.
We should catch the same exception which is raised i.e. ConditionalCheckFailedException not some other exception i.e. ClientError and then add logic to see what that type is. This is non-intuitive exception handling. Next, I see 50 lines of code which handles different kind of exceptions, which would make the except block have more logic than the code itself. Ideally, we should catch the same exception which is being raised.
Again, obviously this is functionally working, but we strive to write intuitive code, right? Either the coe should raise ClientError and we catch the same exception or code raises ConditionalCheckFailedException and we catch the same.
Raising ConditionalCheckFailedException and catching ClientError is misinforming.
@ghsatpute - You can achieve the same using the errorfactory which will create an error class based on the codes returned. This was added here
import boto3
res = boto3.resource('dynamodb')
table = res.Table('mytable')
try:
conditionalUpdateResponse = table.put_item(Item={'test':'testing20'},ConditionExpression='attribute_exists(test)')
except res.meta.client.exceptions.ConditionalCheckFailedException as e:
print(e)
Hope this helps. We don't have very good documentation about how to use errorfactory.
@swetashre Thanks for this update. Now, the exception handling makes sense.
Thanks again for your time.
@swetashre
Is there anyway to do this with boto3 client instead of resource?
@jayfry1077 - Please open a new issue for if you have any concerns. I would be happy to help. We don't have enough bandwidth to follow up on closed issues.
Most helpful comment
@ghsatpute - You can achieve the same using the errorfactory which will create an error class based on the codes returned. This was added here
Hope this helps. We don't have very good documentation about how to use errorfactory.