SageMaker推理脚本初始化S3客户端时触发递归深度超限错误
解决AWS SageMaker推理脚本中boto3 S3客户端递归深度超限错误
问题分析
从错误栈可以明确,递归循环发生在Python标准库ssl.py的SSLContext.options属性赋值环节。这是因为gevent猴子补丁改写了属性访问逻辑,与Python 3.10+版本中SSLContext的super()调用实现产生冲突,最终形成无限递归。
解决方案
方案1:全局初始化S3客户端(最优解)
每次推理请求都创建新的S3客户端不仅会触发递归问题,还会浪费资源。将客户端初始化移至模块全局作用域,仅创建一次:
# 模块顶部执行,仅初始化一次 import boto3 s3_client = boto3.client('s3') def get_video_bytes_from_s3(bucket_name, key): try: video_object = s3_client.get_object(Bucket=bucket_name, Key=key) video_bytes = video_object['Body'].read() return video_bytes except Exception as e: print(f"Failed to fetch video from S3: {e}")
方案2:缩小gevent猴子补丁范围
若必须使用gevent,避免全量补丁,仅patch必要模块并排除ssl:
from gevent import monkey # 只patch核心模块,跳过ssl以避免冲突 monkey.patch_all(ssl=False)
方案3:强制boto3使用原生HTTP会话
让boto3绕过gevent补丁的HTTP会话,改用原生urllib3实现:
from botocore.httpsession import URLLib3Session def get_video_bytes_from_s3(bucket_name, key): # 创建带原生会话的S3客户端 s3_client = boto3.client('s3', config=boto3.session.Config( http_session=URLLib3Session() )) try: video_object = s3_client.get_object(Bucket=bucket_name, Key=key) video_bytes = video_object['Body'].read() return video_bytes except Exception as e: print(f"Failed to fetch video from S3: {e}")
方案4:降级Python版本(临时应急)
若以上方案无法快速落地,可将SageMaker容器的Python版本降级至3.9及以下,该版本的SSLContext实现不会触发此递归问题。
验证方式
将修改后的推理脚本部署到SageMaker端点,测试S3对象读取功能,检查CloudWatch日志是否不再出现递归错误。
内容的提问来源于stack exchange,提问作者Mustapha Unubi Momoh
相关产品推荐
相关产品推荐

