同步前必须确认google_application_credentials环境变量指向有效json密钥、aws credentials中profile具备s3读写权限且region匹配、本地目录不含unc路径或符号链接循环。

同步前必须确认的三个权限和配置项
直接跑脚本却同步失败,八成卡在这三处。不是代码问题,是环境没配好。
用 google-api-python-client 或 boto3 前,先检查:
-
GOOGLE_APPLICATION_CREDENTIALS环境变量是否指向有效的 JSON 密钥文件(不是 P12,不是服务账号邮箱) - AWS 用户需确认
~/.aws/credentials里有带s3:PutObject和s3:GetObject权限的 profile,且region配置与桶所在区域一致 - 本地同步目录不能含 Windows UNC 路径(如
\servershare)或符号链接循环,否则os.walk()会卡死或报RecursionError
用 hashlib 对比文件内容而非仅看修改时间
靠 os.path.getmtime() 判断变更极不可靠:NFS 挂载、Docker 卷、某些云盘客户端会导致时间戳不同步或回拨。
实际做法是为每个文件生成 SHA-256 校验值并缓存,下次同步时只比对校验值:
import hashlib
def file_hash(path):
h = hashlib.sha256()
with open(path, "rb") as f:
while chunk := f.read(8192):
h.update(chunk)
return h.hexdigest()
- 缓存校验值建议存为 SQLite 数据库(比 JSON 文件快 10 倍以上),表结构只需
path TEXT PRIMARY KEY, hash TEXT, size INTEGER - 跳过大小为 0 的文件——它们的 hash 总是相同,但可能只是临时占位,应以存在性为准
- 大文件(>100MB)可先比对 size + mtime,再按需计算 hash,避免 I/O 浪费
处理并发写入导致的“文件正在使用”错误
Windows 上常见 PermissionError: [WinError 32] The process cannot access the file because it is being used by another process,本质是其他程序(如 VS Code、Word、OneDrive)锁住了文件句柄。
- 不要用
try/except直接跳过——这会导致漏同步。改用time.sleep(0.1)后重试,最多 3 次 - 对
.tmp、.part、~$开头的临时文件直接跳过,它们大概率是未写完的中间状态 - Linux/macOS 下注意
/proc/self/fd/可能被占用,同步前加os.stat(path).st_dev判断是否在 tmpfs 上,是则强制跳过
增量上传时如何避免覆盖云端新版本
本地删了文件,但云端还有更新版?或者多人协作时 A 删文件、B 同时改了同名文件?这时单向同步会丢数据。
- 必须启用「双向冲突检测」:上传前先
HEAD请求获取云端Last-Modified和ETag,与本地 hash 比对 - 冲突时默认策略是重命名本地文件为
filename_conflict_20240521T143022,不自动覆盖也不报错退出 - Amazon S3 的
ETag不等于 MD5(分段上传时是 multipart MD5),务必用boto3.head_object(Bucket=..., Key=...)获取真实 ETag,别自己算
真正麻烦的从来不是怎么传上去,而是传上去之后谁动过、什么时候动的、动得对不对——这些信息得靠日志和校验值留痕,而不是依赖某个 SDK 的“智能同步”开关。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











