Answer a question

I have a strange problem with Python Boto3 when trying to do a batch_write_item to a DynamoDB table. I am following the documentation and trying to write a singe item. The table is setup correctly and I can run batch-write-item via the AWS cli no problem.

Assuming the client and DynamoDB are set up correctly I run:

client.batch_write_item(RequestItems={
    "myTable": [
        {
            "PutRequest": {
                "Item": {
                    "name": {
                        "S": "hello"
                    },
                    "value": {
                        "S": "world"
                    }
                }
            }
        }
    ]
})

I get the following error:

botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the BatchWriteItem operation: Invalid attribute value type

If I change it, removing the types and run:

client.batch_write_item(RequestItems={
    "myTable": [
        {
            "PutRequest": {
                "Item": {
                    "name": "hello",
                    "value": "world"
                }
            }
        }
    ]
})

It works as expected.

I need to use the previous format which follows the documentation and is compatibale with AWS cli.

Is the documentation wrong or I missed a configuration setting, version issue or something else?

Answers

This just got me as well, looks like you're using a DynamoDB resource, not a client. They both provide the same function but it acts very slightly differently. Here's what you're looking for:

http://boto3.readthedocs.io/en/latest/reference/services/dynamodb.html#DynamoDB.ServiceResource.batch_write_item

That aside, the docs are still pretty unclear. Here's what I found:

  • When using a resource (what you're currently doing), you may specify the type of non-key attributes, and you must not specify the type of key attributes
  • When using a client (the other option), you must specify the type of all attributes.

Using the DynamoDB resource:

resource = boto3.resource('dynamodb', endpoint_url='http://localhost:8000')

mytable = resource.create_table(
    TableName='mytable',
    KeySchema=[{ 'AttributeName': 'name', 'KeyType': 'HASH' }],
    AttributeDefinitions=[{ 'AttributeName': 'name', 'AttributeType': 'S' }],
    ProvisionedThroughput={ 'ReadCapacityUnits': 5, 'WriteCapacityUnits': 5 }
)

try:
    resource.batch_write_item(RequestItems={
        'mytable': [{ 'PutRequest': { 'Item': {
            'name': { 'S': 'myname' },
            'value': { 'S': 'myvalue' }
        }}}]
    })
    print(f'resource, specify all types : write succeeded.')
except Exception as e:
    print(f'resource, specify all types : write failed: {e}')

try:
    resource.batch_write_item(RequestItems={
        'mytable': [{ 'PutRequest': { 'Item': {
            'name': 'myname',
            'value': { 'S': 'myvalue' }
        }}}]
    })
    print(f'resource, specify value only: write succeeded.')
except Exception as e:
    print(f'resource, specify value only: write failed: {e}')

try:
    resource.batch_write_item(RequestItems={
        'mytable': [{ 'PutRequest': { 'Item': {
            'name': 'myname',
            'value': 'myvalue'
        }}}]
    })
    print(f'resource, specify none      : write succeeded.')
except Exception as e:
    print(f'resource, specify none      : write failed: {e}')

Output

resource, specify all types : write failed:
    An error occurred (ValidationException) when calling the BatchWriteItem operation: Invalid attribute value type
resource, specify value only: write succeeded.
resource, specify none      : write succeeded.

And then using the DynamoDB client (replace all "resource"s above with client)

client = boto3.client('dynamodb', endpoint_url='http://localhost:8000')
try:
    client.batch_write_item(RequestItems={    
....

Output

client, specify all types : write succeeded.
client, specify value only: write failed: Parameter validation failed:
    Invalid type for parameter RequestItems.mytable[0].PutRequest.Item.name, value: myname, type: <class 'str'>, valid types: <class 'dict'>
client, specify none      : write failed: Parameter validation failed:
    Invalid type for parameter RequestItems.mytable[0].PutRequest.Item.name, value: myname, type: <class 'str'>, valid types: <class 'dict'>
    Invalid type for parameter RequestItems.mytable[0].PutRequest.Item.value, value: myvalue, type: <class 'str'>, valid types: <class 'dict'>
Logo

Python社区为您提供最前沿的新闻资讯和知识内容

更多推荐