AWS Lambda运行Python脚本报dbresponse未定义NameError
DynamoDB更新脚本本地运行正常、Lambda部署后报NameError问题排查
问题现象
- 编写的Python脚本用于更新DynamoDB指定字段值并返回更新结果,在VSCode环境连接AWS服务运行时无报错、执行正常;调整为Lambda适配格式部署后,测试运行触发错误。
本地可正常运行的VSCode代码
import boto3 from boto3.dynamodb.conditions import Key, Attr dynamodb = boto3.resource('dynamodb',region_name='us-east-1') table = dynamodb.Table('Visitors') response = table.update_item( Key={'ID': 0}, UpdateExpression="ADD #ct :increment", ExpressionAttributeNames={'#ct': 'visitorcount'}, ExpressionAttributeValues={':increment': 1}, ReturnValues = "UPDATED_NEW" ) visitorCount = int(response["Attributes"]["visitorcount"]) print('visitorCount obtained from table = ' + str(visitorCount))
部署到Lambda的问题代码
import json import boto3 from boto3.dynamodb.conditions import Key, Attr dynamodb = boto3.resource('dynamodb',region_name='us-east-1') table = dynamodb.Table('Visitors') def lambda_handler(event, context): dbresponse = table.update_item( Key={'ID': 0}, UpdateExpression="ADD #ct :increment", ExpressionAttributeNames={'#ct': 'visitorcount'}, ExpressionAttributeValues={':increment': 1}, ReturnValues = "UPDATED_NEW" ) visitorCount = int(dbresponse["Attributes"]["visitorcount"]) print('visitorCount obtained from table = ' + str(visitorCount))
Lambda测试报错信息
- 测试事件名称:mycodetest
{ "errorMessage": "name 'dbresponse' is not defined", "errorType": "NameError", "requestId": "", "stackTrace": [ " File \"/var/lang/lib/python3.9/importlib/__init__.py\", line 127, in import_module\n return _bootstrap._gcd_import(name[level:], package, level)\n", " File \"<frozen importlib._bootstrap>\", line 1030, in _gcd_import\n", " File \"<frozen importlib._bootstrap>\", line 1007, in _find_and_load\n", " File \"<frozen importlib._bootstrap>\", line 986, in _find_and_load_unlocked\n", " File \"<frozen importlib._bootstrap>\", line 680, in _load_unlocked\n", " File \"<frozen importlib._bootstrap_external>\", line 850, in exec_module\n", " File \"<frozen importlib._bootstrap>\", line 228, in _call_with_frames_removed\n", " File \"/var/task/lambda_function.py\", line 18, in <module>\n visitorCount = int(dbresponse[\"Attributes\"][\"visitorcount\"])\n" ] }
故障根因
报错由两个缩进错误直接导致:
- 变量
dbresponse定义在lambda_handler函数内部,属于函数局部变量,但读取dbresponse、计算访客数、打印结果的代码写在了lambda_handler函数外部的全局作用域。Lambda加载代码文件时会先执行全局作用域代码,此时lambda_handler还未被触发,内部的dbresponse变量根本没有被创建,直接触发NameError。 update_item方法的ReturnValues参数缩进错误,没有和同属方法入参的Key、UpdateExpression等参数保持同级缩进,会被Python识别为函数外部的代码,触发语法层面的异常。
修复后可正常运行的Lambda代码
import json import boto3 from boto3.dynamodb.conditions import Key, Attr # DynamoDB资源初始化放在全局作用域是正确写法,Lambda会复用执行环境的已有资源,降低冷启动耗时 dynamodb = boto3.resource('dynamodb', region_name='us-east-1') table = dynamodb.Table('Visitors') def lambda_handler(event, context): dbresponse = table.update_item( Key={'ID': 0}, UpdateExpression="ADD #ct :increment", ExpressionAttributeNames={'#ct': 'visitorcount'}, ExpressionAttributeValues={':increment': 1}, ReturnValues="UPDATED_NEW" ) # 所有依赖dbresponse的逻辑全部放在lambda_handler函数内部,保持4空格统一缩进 visitorCount = int(dbresponse["Attributes"]["visitorcount"]) print('visitorCount obtained from table = ' + str(visitorCount)) # 符合Lambda规范的HTTP返回格式 return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*' }, 'body': json.dumps({ 'visitorCount': visitorCount }) }
部署前注意项
- 给Lambda绑定的执行角色添加DynamoDB表
Visitors的dynamodb:UpdateItem权限,否则修复缩进后会触发权限拒绝错误 - Python是严格缩进敏感的语言,代码块内统一使用4空格缩进,不要混用空格和Tab键,避免出现非预期的作用域错误
内容的提问来源于stack exchange,提问作者CurtFarley
相关产品推荐
相关产品推荐

