使用Python在Lambda中查询DynamoDB时出现内部服务器错误
问题描述
我正在尝试通过API Gateway的Lambda代理集成,读取分区键为Name的DynamoDB表saved_measurements。已经确认event['pathParameters']['name']功能正常,排除了这个因素的影响。但通过Name查询表时,会返回错误:{"message": "Internal server error"}。我查了很多DynamoDB查询的资料都没解决,当响应体返回示例字符串(比如"yes")时一切正常,只有返回查询数据时才会触发这个错误。该怎么解决?
import json import boto3 from boto3.dynamodb.conditions import Key, Attr def lambda_handler(event, context): client = boto3.resource('dynamodb') table = client.Table('saved_measurements') data = table.query(KeyConditionExpression=Key('Name').eq(event['pathParameters']['name'])) stuff = data.Items response = { "statusCode": 200, "headers": { "Content-Type": 'application/json', "Access-Control-Allow-Origin" : "*", "Access-Control-Allow-Headers" : "Content-Type", "Access-Control-Allow-Methods": "OPTIONS,POST,GET" }, "body": json.dumps(stuff), "isBase64Encoded": False } return response
解决方向
1. 修复DynamoDB结果的序列化问题
DynamoDB返回的数据中常包含Decimal等Python标准JSON编码器无法处理的类型,这是触发内部错误的最常见原因。可以自定义编码器解决:
import json from decimal import Decimal class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, Decimal): # 根据数值类型转换为int或float return int(o) if o % 1 == 0 else float(o) return super().default(o)
然后在序列化时指定该编码器:
"body": json.dumps(stuff, cls=DecimalEncoder),
2. 修正结果集的访问方式
原代码中stuff = data.Items是错误的,boto3资源模式下table.query()返回的是字典对象,需通过键名访问结果列表:
stuff = data['Items']
3. 添加错误捕获与日志输出
Lambda内部错误需要查看CloudWatch日志定位,添加异常捕获可以直接返回错误信息,便于排查:
def lambda_handler(event, context): try: client = boto3.resource('dynamodb') table = client.Table('saved_measurements') data = table.query(KeyConditionExpression=Key('Name').eq(event['pathParameters']['name'])) stuff = data['Items'] response = { "statusCode": 200, "headers": { "Content-Type": 'application/json', "Access-Control-Allow-Origin" : "*", "Access-Control-Allow-Headers" : "Content-Type", "Access-Control-Allow-Methods": "OPTIONS,POST,GET" }, "body": json.dumps(stuff, cls=DecimalEncoder), "isBase64Encoded": False } return response except Exception as e: # 打印日志到CloudWatch print(f"Query failed: {str(e)}") return { "statusCode": 500, "headers": { "Content-Type": 'application/json', "Access-Control-Allow-Origin" : "*", "Access-Control-Allow-Headers" : "Content-Type", "Access-Control-Allow-Methods": "OPTIONS,POST,GET" }, "body": json.dumps({"error": str(e)}), "isBase64Encoded": False }
4. 验证Lambda执行角色权限
确保Lambda的执行角色拥有dynamodb:Query权限,且资源范围包含目标表。示例权限策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "dynamodb:Query", "Resource": "arn:aws:dynamodb:你的AWS区域:你的账号ID:table/saved_measurements" } ] }
5. 确认分区键的大小写匹配
DynamoDB的属性名区分大小写,需确保表的分区键确实是Name(而非name或其他变体)。
内容的提问来源于stack exchange,提问作者beefwhale
相关产品推荐
相关产品推荐

