AWS Lambda异常处理问题:无法忽略NoSuchKey错误?
Lambda处理S3批量文件时NoSuchKey错误捕获异常问题排查
问题场景
我有一个用于验证文件完整性的Lambda函数(可简化为S3跨桶复制逻辑),当批量上传大量文件到S3时,函数会被多次触发。先执行的调用会处理多个文件,后触发的调用因文件已被处理而抛出NoSuchKey错误。我添加了try-except逻辑,打算把该错误记录为INFO级日志,避免触发监控ERROR关键字的告警,但实际运行时CloudWatch日志中先出现ERROR级别的报错信息,随后才是except块里记录的No object found - File has been moved INFO日志,仿佛try和except的逻辑都执行了。
我的代码如下:
import botocore import boto3 import logging # Set up our logger logging.basicConfig(level=logging.INFO) logger = logging.getLogger() client = boto3.client('s3') try: logger.info('Executing copy statement') # main logic except botocore.exceptions.ClientError as error: if error.response['Error']['Code'] == 'NoSuchKey': logger.info('No object found - File has been moved') else: raise error
问题原因
出现这种现象的核心原因是boto3底层的日志器会在抛出ClientError之前,先将错误信息以ERROR级别输出,而你的日志配置没有覆盖boto3的默认日志级别。具体来说:
- Lambda环境中默认已经配置了日志处理,
logging.basicConfig可能不会完全覆盖原有配置 - boto3的内部日志器(比如
botocore、boto3)默认日志级别为ERROR,当NoSuchKey错误发生时,这些日志器会先输出错误日志,之后才进入你的except代码块执行日志记录
解决方案
你需要调整boto3相关日志器的级别,禁止它们输出ERROR级别的日志,只保留自己的日志逻辑:
修改后的代码如下:
import botocore import boto3 import logging # 调整根日志器级别,并禁用boto3相关日志器的输出 logger = logging.getLogger() logger.setLevel(logging.INFO) # 禁止botocore和boto3的日志输出,避免干扰自定义日志 for handler in logger.handlers: handler.setLevel(logging.INFO) logging.getLogger('botocore').setLevel(logging.WARNING) logging.getLogger('boto3').setLevel(logging.WARNING) client = boto3.client('s3') try: logger.info('Executing copy statement') # 这里替换为你的跨桶复制或文件完整性验证逻辑 # 示例:client.copy_object(CopySource='source-bucket/key', Bucket='dest-bucket', Key='dest-key') except botocore.exceptions.ClientError as error: if error.response['Error']['Code'] == 'NoSuchKey': logger.info('No object found - File has been moved') else: # 非NoSuchKey错误仍抛出,触发原有告警逻辑 raise error
关键调整点
- 直接设置根日志器的级别,而不是用
logging.basicConfig(Lambda环境中该方法可能不生效) - 将
botocore和boto3的日志级别设为WARNING或更高,这样它们就不会输出NoSuchKey这类ERROR级别的日志 - 确保自定义的日志逻辑是唯一的错误信息输出源
补充建议
除了日志调整,你还可以从根源上减少不必要的Lambda调用:
- 配置S3事件通知的批量触发:设置更大的批量大小和更长的触发等待时间,让一次Lambda调用处理更多文件
- 使用S3版本控制或临时标记:处理文件时给源文件添加自定义标记,后续调用先检查标记再执行逻辑,避免重复处理
内容的提问来源于stack exchange,提问作者Kewei
相关产品推荐
相关产品推荐

