You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python日志流式传输至S3报递归深度超限错误的解决方法

问题根源

这个递归错误的核心原因是boto3客户端本身会使用Python的logging模块输出日志,而你把S3Handler加到了根日志器(logging.getLogger())上。当emit方法调用put_object时,boto3会产生日志,根日志器又会把这些日志交给S3Handler处理,触发新一轮的emit调用,循环往复直到超出递归深度。

解决方法

方法1:给应用日志单独分配Logger

不要把S3Handler绑定到根日志器,而是给你的应用代码创建专属Logger,只给这个Logger添加S3Handler。这样boto3的日志会走默认的handler,不会触发递归。

# 创建应用专属Logger
app_logger = logging.getLogger("my_app")
app_logger.setLevel(logging.INFO)

# 初始化S3Handler并绑定到应用Logger
s3_handler = S3Handler(bucket_name='mybucketname', key='path/to/logfile.txt')
app_logger.addHandler(s3_handler)

# 应用代码中使用这个Logger打日志
app_logger.info("应用启动")
app_logger.error("发生错误")

方法2:在emit方法中防止重入

在emit执行期间,通过标志位禁止重入调用,避免递归循环。

class S3Handler(logging.StreamHandler):
    def __init__(self, bucket_name, key):
        super().__init__()
        self.bucket_name = bucket_name
        self.key = key
        self.s3_client = boto3.client('s3',
            endpoint_url=...,
            aws_access_key_id=...,
            aws_secret_access_key=...)
        self._is_processing = False  # 重入控制标志

    def emit(self, record):
        # 如果正在处理日志,直接返回,避免递归
        if self._is_processing:
            return
        try:
            self._is_processing = True
            log_entry = self.format(record).encode('utf-8')
            self.s3_client.put_object(Bucket=self.bucket_name, Key=self.key, Body=log_entry, ACL="public-read")
        except Exception as e:
            # 这里不要用logging,避免再次触发递归,直接用print输出错误
            print(f"Error while logging to S3: {str(e)}")
        finally:
            self._is_processing = False

方法3:限制boto3的日志级别

如果不需要boto3的调试日志,可以把boto3相关日志器的级别设为WARNING或更高,减少递归触发的概率。

# 禁用boto3系列的低级别日志
logging.getLogger('boto3').setLevel(logging.WARNING)
logging.getLogger('botocore').setLevel(logging.WARNING)
logging.getLogger('s3transfer').setLevel(logging.WARNING)
额外提醒

你当前的代码每次调用put_object都会覆盖S3上的同一个文件,脚本运行结束后只会保留最后一条日志。如果要完整保存所有日志,可以考虑:

  • 给日志文件key添加时间戳(比如path/to/logs/{datetime.now()}.txt),生成独立的日志文件
  • 先将日志写入本地文件,再定期批量上传到S3
  • 使用S3的追加写入机制(需要结合Content-Range参数,实现相对复杂)

内容的提问来源于stack exchange,提问作者user984621

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:52:47