AWS Lambda Python Boto3启动EC2实例遇UnboundLocalError问题咨询
解决UnboundLocalError:'each_scheduled_instance' referenced before assignment
问题原因
你的代码在启动EC2实例时触发UnboundLocalError,根源有两点:
- 变量未定义场景:如果AWS账号下没有任何EC2实例,
for each_scheduled_instance in ec2_console_resource.instances.all()循环根本不会执行,each_scheduled_instance变量从未被赋值,后续调用each_scheduled_instance.wait_until_running()自然会报错。 - 逻辑缺陷:就算存在EC2实例,当前写法也只会等待最后一个启动的实例进入运行状态,其他实例的启动状态没有被监控。
报错信息
{ "errorMessage": "local variable 'each_scheduled_instance' referenced before assignment", "errorType": "UnboundLocalError", "requestId": "3054209f-5cf7-429e-bcc7-7109a3b28a29", "stackTrace": [ " File \"/var/task/lambda_function.py\", line 19, in lambda_handler\n return dealwithec2instances(event)\n", " File \"/var/task/lambda_function.py\", line 25, in dealwithec2instances\n return ec2_instances_start(event)\n", " File \"/var/task/lambda_function.py\", line 40, in ec2_instances_start\n each_scheduled_instance.wait_until_running()\n" ] }
原代码
import boto3 import logging import os from pprint import pprint logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): varbotname = event['bot']['name'] logger.info('bot name is ' +str(varbotname)) return dealwithec2instances(event) def dealwithec2instances(event): print('in dealwithec2instances') intentname = event['currentIntent']['name'] if intentname == 'StartInstances': return ec2_instances_start(event) def ec2_instances_start(event): print('in ec2 instances method') aws_mgmt_console = boto3.session.Session() ec2_console_resource = aws_mgmt_console.resource('ec2') ec2_console_client = aws_mgmt_console.client('ec2') waiter=ec2_console_client.get_waiter('instance_running') for each_scheduled_instance in ec2_console_resource.instances.all(): each_scheduled_instance.start() each_scheduled_instance.wait_until_running() return 'success'
修复方案
方案一:逐个实例等待启动(资源API方式)
先检查是否存在实例,再逐个启动并等待:
import boto3 import logging import os from pprint import pprint logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): varbotname = event['bot']['name'] logger.info('bot name is ' +str(varbotname)) return dealwithec2instances(event) def dealwithec2instances(event): print('in dealwithec2instances') intentname = event['currentIntent']['name'] if intentname == 'StartInstances': return ec2_instances_start(event) def ec2_instances_start(event): print('in ec2 instances method') aws_mgmt_console = boto3.session.Session() ec2_console_resource = aws_mgmt_console.resource('ec2') # 获取所有实例并转换为列表,方便检查是否为空 instances = list(ec2_console_resource.instances.all()) if not instances: logger.info("No EC2 instances found to start") return 'no_instances_found' # 逐个启动并等待实例进入运行状态 for each_instance in instances: each_instance.start() each_instance.wait_until_running() return 'success'
方案二:批量等待实例启动(客户端API方式,效率更高)
使用EC2客户端的waiter批量监控所有实例状态,适合大量实例场景:
import boto3 import logging import os from pprint import pprint logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): varbotname = event['bot']['name'] logger.info('bot name is ' +str(varbotname)) return dealwithec2instances(event) def dealwithec2instances(event): print('in dealwithec2instances') intentname = event['currentIntent']['name'] if intentname == 'StartInstances': return ec2_instances_start(event) def ec2_instances_start(event): print('in ec2 instances method') aws_mgmt_console = boto3.session.Session() ec2_console_client = aws_mgmt_console.client('ec2') # 收集所有实例ID instance_ids = [] response = ec2_console_client.describe_instances() for reservation in response['Reservations']: for instance in reservation['Instances']: instance_ids.append(instance['InstanceId']) if not instance_ids: logger.info("No EC2 instances found to start") return 'no_instances_found' # 批量启动实例 ec2_console_client.start_instances(InstanceIds=instance_ids) # 使用waiter等待所有实例进入运行状态 waiter = ec2_console_client.get_waiter('instance_running') waiter.wait(InstanceIds=instance_ids) return 'success'
修改说明
- 新增实例存在性检查,避免无实例时变量未定义的错误
- 方案一保持资源API的简洁性,适合少量实例;方案二用客户端API批量操作,效率更高
- 确保所有启动的实例都被监控到运行状态,修复原逻辑只等待最后一个实例的缺陷
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

