核心逻辑是用os.listdir()遍历目录,结合os.path.getmtime()获取文件修改时间戳,与time.time()比较是否超期;须用os.path.isfile()过滤目录、os.path.join()拼接路径;推荐pathlib.path.rglob()替代递归,删除前校验is_file()并捕获异常,清理目录需谨慎使用shutil.rmtree()。

用 os.listdir() + os.path.getmtime() 判断文件是否过期
核心逻辑是遍历目录,获取每个文件的最后修改时间,和当前时间比对是否超过保留天数。注意:os.path.getmtime() 返回的是时间戳(秒级),不是 datetime 对象,直接减法会出错;得统一转成 time.time() 的单位做比较。
常见错误是误用 os.path.getctime() —— 在 Linux 上它是“inode 创建时间”,不等于“文件创建时间”,且日志轮转后可能被重写,mtime 更可靠。
实操建议:
- 用
time.time() - os.path.getmtime(path) > days * 86400判断是否过期(避免引入datetime增加复杂度) - 先用
os.path.isfile(path)过滤掉子目录,否则删目录会报IsADirectoryError - 路径拼接务必用
os.path.join(root, f),别用字符串拼接,Windows 下会出错
用 pathlib.Path.rglob() 替代递归遍历更简洁
如果需要清理子目录里的日志(比如 logs/app1/、logs/app2/),os.walk() 写起来啰嗦。pathlib 是 Python 3.4+ 的推荐方式,.rglob("*.log") 一行就能扫全匹配文件。
注意点:
-
rglob()返回的是Path对象,调.stat().st_mtime拿修改时间,不是.getmtime() - 删除前加
if p.is_file():防止误删空目录(rglob可能匹配到目录名含 .log 的文件夹) - 不要用
p.unlink(missing_ok=True)(Python 3.8+ 才支持),低版本需包try/except FileNotFoundError
用 shutil.rmtree() 清理整个过期日志目录时要格外小心
有些场景要求“清空整个目录”(比如每天生成一个 logs/2024-05-01/),而不是只删文件。这时不能只遍历删内容,得判断目录本身的修改时间。
关键风险:
-
shutil.rmtree()不回收站,删完不可逆;必须先print()或记录到日志里待删路径 - 不能对
logs/根目录本身做时间判断——它可能长期存在,应判断其子目录名是否含日期,或用path.stat().st_mtime - 若目录非空但含只读文件(如某些日志库生成的
.gz),rmtree()会失败;加onerror回调临时改权限再删
加 logging 和异常捕获避免脚本静默失败
定时任务里最怕脚本跑一半卡住或报错退出却不通知。尤其 PermissionError(文件正被写入)、OSError: [WinError 32](Windows 下进程占用)很常见。
最小可用建议:
- 用
logging.basicConfig(level=logging.INFO, filename="cleanup.log")记录删了哪些、跳过了哪些 - 每个
os.remove()或path.unlink()包try/except (OSError, PermissionError) as e:,logging.warning(f"skip {path}: {e}") - 别用
sys.exit(1)中断整个流程——单个文件失败不该影响其他清理
真正难的不是写几行删除代码,而是确认“这个文件此刻真的没被任何进程打开”。生产环境建议配合 lsof(Linux/macOS)或 handle.exe(Windows)预检,或者让日志框架本身支持按大小/时间自动轮转并删除旧文件——脚本只是兜底手段。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











