Python如何实现文件达指定大小后覆盖开头旧内容循环写入
固定大小日志循环覆盖实现方案
你当前用的"a"追加写入模式是操作系统提供的基础文件操作模式,仅支持在文件末尾追加内容,原生不支持达到阈值后自动覆盖开头旧内容的能力,需要额外加一层大小判断和截断逻辑实现需求,有两种常用实现路径。
手动实现轻量逻辑
核心逻辑分三步:
- 每次写入前先检查日志文件当前字节大小
- 若当前文件大小加本次写入内容的总大小未超过50MB阈值,直接走追加写入逻辑
- 若总大小超过阈值,先读取文件末尾需要保留的内容(保证保留内容+新内容总大小不超阈值),再从文件开头覆盖写入,截断多余的头部旧内容即可
可直接复用的实现代码:
import os LOG_FILE_PATH = "mylogfile.log" # 50MB对应字节数 MAX_FILE_SIZE = 50 * 1024 * 1024 def write_to_log(text: str): # 统一补全换行符,对齐常规日志行格式 if not text.endswith("\n"): text += "\n" text_bytes = text.encode("utf-8") text_len = len(text_bytes) # 文件不存在时直接创建写入 if not os.path.exists(LOG_FILE_PATH): with open(LOG_FILE_PATH, "wb") as f: f.write(text_bytes) return current_size = os.path.getsize(LOG_FILE_PATH) # 未达阈值,正常追加 if current_size + text_len <= MAX_FILE_SIZE: with open(LOG_FILE_PATH, "ab") as f: f.write(text_bytes) return # 达到阈值,执行截断覆盖 keep_old_length = MAX_FILE_SIZE - text_len with open(LOG_FILE_PATH, "rb+") as f: # 定位到文件末尾往前数保留长度的位置,读取需要留存的旧内容 f.seek(-keep_old_length, os.SEEK_END) keep_content = f.read() # 回到文件开头,写入留存旧内容+新内容,截断多余部分 f.seek(0) f.write(keep_content) f.write(text_bytes) f.truncate()
使用注意事项:
- 如果要求日志必须按整行保留、不允许出现半行截断的情况,可以在读取到
keep_content后,先找到第一个换行符的位置,丢弃换行符前的半截内容再写入,避免日志行断裂 - 用二进制模式读写可以规避不同编码下的长度计算误差,稳定性比文本模式更高
生产场景推荐用标准库实现
如果是正式业务场景使用,不需要手写上述逻辑,Python标准库logging模块自带的RotatingFileHandler已经封装好了按文件大小滚动的逻辑,只要把备份数设为0,就能实现单文件达到阈值后循环覆盖的效果,比手写逻辑更稳定,自带并发锁、编码适配、整行写入的处理。
示例代码:
import logging from logging.handlers import RotatingFileHandler MAX_FILE_SIZE = 50 * 1024 * 1024 # 初始化日志实例 logger = logging.getLogger("custom_log") logger.setLevel(logging.INFO) # 配置大小滚动处理器,backupCount设为0即不生成额外备份文件,单文件循环覆盖 file_handler = RotatingFileHandler( "mylogfile.log", maxBytes=MAX_FILE_SIZE, backupCount=0, encoding="utf-8" ) logger.addHandler(file_handler) # 后续写入直接调用对应方法即可,自动处理大小判断和覆盖逻辑 logger.info("需要写入的日志内容")
内容的提问来源于stack exchange,提问作者Dibidalidomba
相关产品推荐
相关产品推荐

