最直接方案是用shutil.make_archive配合datetime.strftime生成安全时间戳归档名(如20240521_143022),指定格式与源目录路径;需确保目标父目录存在,避免filenotfounderror。

用 shutil.make_archive 打包并按日期命名最直接
Python 标准库自带方案,不依赖第三方包,适合轻量备份。关键点是生成带当前日期的归档名,再调用打包函数。
常见错误是直接拼接 datetime.now() 字符串导致非法文件名(如冒号、空格),必须格式化为安全字符串。
- 用
datetime.now().strftime("%Y%m%d_%H%M%S")生成形如20240521_143022的时间戳 -
shutil.make_archive的第一个参数是归档路径(不含扩展名),第二个参数指定格式("zip"或"tar"),第三个参数是待备份的根目录 - 注意:目标路径的父目录必须已存在,否则抛出
FileNotFoundError
import shutil
import datetime
<p>src<em>dir = "/home/user/docs"
timestamp = datetime.datetime.now().strftime("%Y%m%d</em>%H%M%S")
archive<em>path = f"/backup/docs</em>{timestamp}"</p><p>shutil.make_archive(archive_path, "zip", src_dir)</p>
用 pathlib + os.walk 实现细粒度控制(比如跳过缓存)
当需要排除特定子目录(如 .git、__pycache__)或只备份某类文件时,shutil.make_archive 不够灵活,得手动遍历+压缩。
核心思路是用 pathlib.Path 构建路径,配合 os.walk 过滤,再用 zipfile.ZipFile 逐个写入。
- 过滤逻辑放在
os.walk的topdown=True模式下,修改dirs列表可跳过子目录 - 写入 ZIP 时,用
arcname参数重写内部路径,避免绝对路径被存进去 - 别忘了用
with管理ZipFile,否则可能写入不完整
import zipfile
import os
from pathlib import Path
<p>src = Path("/home/user/project")
dst = Path(f"/backup/project_{datetime.datetime.now():%Y%m%d}.zip")</p><p>with zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED) as zf:
for root, dirs, files in os.walk(src, topdown=True):</p><h1>跳过这些目录</h1><pre class="brush:python;toolbar:false;"> dirs[:] = [d for d in dirs if d not in {".git", "__pycache__"}]
for file in files:
fp = Path(root) / file
# 用相对路径作为 ZIP 内部路径
arcname = fp.relative_to(src)
zf.write(fp, arcname)
备份失败时容易忽略的权限和符号链接问题
在 Linux/macOS 上,如果源目录含符号链接或需读取权限受限的文件,shutil.make_archive 默认会静默跳过或报错,但错误信息不明显。
典型现象:生成的 ZIP 文件比预期小很多,或者报 PermissionError: [Errno 13] Permission denied 却没定位到具体文件。
- 加
error_cb回调函数捕获异常(仅限 Python 3.9+),或提前用os.access(src, os.R_OK)检查可读性 - 符号链接默认不展开——若要备份链接指向的内容,需在遍历时用
fp.resolve();若要保留链接本身,得用zipfile.ZipInfo手动设置is_dir和external_attr - Windows 下注意长路径限制(
MAX_PATH),建议启用长路径支持或改用 UNC 路径
定时执行别硬写循环,交给系统级调度更可靠
在脚本里用 time.sleep() 循环做定时备份,一旦进程退出或机器重启就中断,不可靠。
真正落地时,应把备份脚本当作一次性任务,由外部调度器驱动:
- Linux/macOS:用
cron,例如每天凌晨 2 点运行0 2 * * * /usr/bin/python3 /backup/backup.py - Windows:用任务计划程序,触发器设为“按预定计划”,操作为“启动程序”指向
python.exe并传入脚本路径 - 避免在脚本中写死路径,改用
Path(__file__).parent获取当前目录,或通过环境变量传参
日期标注逻辑本身没问题,但如果你发现多个备份挤在同一个时间戳下,大概率是调度器并发启动了两次——加个简单锁文件或检查 ps aux | grep backup.py 就能定位。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











