本地运行AWS Lambda函数报string indices must be integers错误
本地运行AWS Lambda函数抛出
String indices must be integers错误排查 错误复现信息
本地执行Lambda函数时触发如下类型错误:
String indices must be integers
错误栈定位异常触发位置为代码行payload = loads(record['body'], parse_float=str)。
对应Lambda函数代码
def lambda_handler(event, context): logger.debug('Received event: {}'.format(event)) print(event['Item']) operations = { 'DELETE': lambda dynamo, x: dynamo.delete_item(**x), 'POST': lambda dynamo, x: dynamo.put_item(**x), 'PUT': lambda dynamo, x: dynamo.update_item(**x), 'GET': lambda dynamo, x: dynamo.get_item(**x), 'GET_ALL': lambda dynamo, x: dynamo.scan(**x), 'BATCH_WRITE': lambda dynamo, x: dynamo.batch_write_item(**x), } for record in event['Item']: print(record['body']) payload = loads(record['body'], parse_float=str) operation = record['messageAttributes']['Method']['stringValue'] if operation in operations: try: operations[operation](dynamo_client, payload) logger.info('{} method successful'.format(operation)) logger.debug('Event payload: {}'.format(payload)) except Exception as e: logger.error(e) else: logger.error('Unsupported method \'{}\''.format(operation)) return 0
本地测试传入的事件JSON
{ "TableName":"DemoTable", "Item": {"make":{"S":"Ford"}, "type":{"S":"Sedan"}, "fuelType":{"S":"gas"}, "miles":{"S":"50000"}, "model":{"S":"Fiesta"}, "year":{"S":"2018"}} }
完整错误日志
[DEBUG] 2022-07-03T15:09:24.716Z Received event: {'TableName': 'DemoTable', 'Item': {'make': {'S': 'Ford'}, 'type': {'S': 'Sedan'}, 'fuelType': {'S': 'gas'}, 'miles': {'S': '50000'}, 'model': {'S': 'Fiesta'}, 'year': {'S': '2018'}}} {'make': {'S': 'Ford'}, 'type': {'S': 'Sedan'}, 'fuelType': {'S': 'gas'}, 'miles': {'S': '50000'}, 'model': {'S': 'Fiesta'}, 'year': {'S': '2018'}} payload = loads(record['body'], parse_float=str)r END {"errorMessage": "string indices must be integers", "errorType": "TypeError", "stackTrace": [" File \"/var/task/app.py\", line 29, in lambda_handler\n payload = loads(record['body'], parse_float=str)\n"]}
错误根因
- 直接触发报错的语法问题:Python中直接对字典做
for x in dict迭代时,循环拿到的x是字典的键,不是键对应的值,也不是键值对元组。传入的event['Item']是存储车辆属性的字典,迭代时依次返回的是'make'、'type'、'fuelType'这类字符串值。后续代码对字符串类型的record执行record['body']操作时,Python规定字符串的索引必须是整数(比如取字符串第n位用s[n]),传入字符串'body'作为索引就会直接抛出String indices must be integers错误。 - 深层逻辑不匹配问题:现有循环处理逻辑是适配SQS触发Lambda的事件格式的——这种场景下事件里的记录列表应该是数组类型,每个数组元素是单条消息,包含
body(序列化的消息内容)、messageAttributes(消息自定义属性)字段。但本地传入的Item是DynamoDB单条数据格式的字典,和代码预期的结构完全不匹配,就算修复了迭代的语法问题,后续也会因为找不到body、messageAttributes字段继续报错。
修复方案
根据实际业务场景二选一即可:
- 场景1:Lambda仅需处理单条DynamoDB数据写入,不需要支持多操作、批量消息
删掉适配SQS批量消息的循环逻辑,直接从event中提取参数构造DynamoDB请求即可,参考代码:from json import loads import boto3 import logging logger = logging.getLogger() logger.setLevel(logging.INFO) dynamo_client = boto3.client('dynamodb') def lambda_handler(event, context): logger.debug('Received event: {}'.format(event)) payload = { "TableName": event["TableName"], "Item": event["Item"] } try: dynamo_client.put_item(**payload) logger.info('POST method successful') logger.debug('Event payload: {}'.format(payload)) except Exception as e: logger.error(e) return -1 return 0 - 场景2:需要保留原有支持多DynamoDB操作、批量处理消息的逻辑
把本地测试的事件结构改成代码预期的格式:Item字段为数组类型,每个数组元素包含序列化后操作参数的body字段、标记操作类型的messageAttributes字段,参考测试事件:{ "Item": [ { "body": "{\"TableName\": \"DemoTable\", \"Item\": {\"make\": {\"S\": \"Ford\"}, \"type\": {\"S\": \"Sedan\"}, \"fuelType\": {\"S\": \"gas\"}, \"miles\": {\"S\": \"50000\"}, \"model\": {\"S\": \"Fiesta\"}, \"year\": {\"S\": \"2018\"}}}", "messageAttributes": { "Method": { "stringValue": "POST" } } } ] }
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

