zipfile.ZipFile.open() 报“Bad password”主因是仅支持ZipCrypto加密,不支持AES-256;且密码须为bytes类型、仅对加密文件项传入,中文密码还需按CP437编码。

zipfile.ZipFile.open() 为什么总报错“Bad password”
Python 标准库 zipfile 对加密 Zip 的支持非常有限:它**只支持传统 ZIP 加密(ZipCrypto)**,不支持更常见的 AES-256 加密。如果你用 WinRAR、7-Zip 或 macOS 归档工具默认生成的加密 zip,大概率是 AES 加密,zipfile 会直接抛出 RuntimeError: Bad password,哪怕密码完全正确。
判断方法很简单:用 unzip -l -v archive.zip(Linux/macOS)或在 7-Zip 中右键 → “属性”,看加密方式是否标为 “AES-256”。如果是,zipfile 就无能为力了。
实操建议:
- 确认加密类型——别浪费时间反复试密码
- 若为 ZipCrypto(老式加密),可用
zipfile;否则必须换工具 - Windows 自带的“压缩文件夹”功能生成的加密 zip 通常是 ZipCrypto,可尝试
用 zipfile 正确解压 ZipCrypto 加密 zip 的完整流程
即使加密类型匹配,zipfile 的 API 也容易误用:不能直接在 ZipFile 构造时传密码,而必须在调用 .open() 时通过 pwd 参数传入 bytes 类型密码。
立即学习“Python免费学习笔记(深入)”;
常见错误写法:zipfile.ZipFile("a.zip", pwd="123") —— 这会报错,因为 pwd 不是 ZipFile.__init__ 的合法参数。
正确做法:
- 密码必须是
bytes,不是str:用b"123"或"123".encode() - 每个
.open()调用都要单独传pwd,不能“全局设密码” - 仅对加密文件项(
ZipInfo.flag_bits & 0x1为真)才需传pwd;非加密文件传了会报错
示例代码片段:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
import zipfile
<p>with zipfile.ZipFile("secure.zip") as z:
for info in z.filelist:
try:</p><h1>只对加密文件使用 pwd</h1><pre class="brush:php;toolbar:false;"> if info.flag_bits & 0x1:
with z.open(info, pwd=b"mypass") as f:
content = f.read()
print(f"解密读取 {info.filename}: {len(content)} 字节")
else:
with z.open(info) as f:
content = f.read()
except RuntimeError as e:
if "Bad password" in str(e):
print(f"密码错误或非 ZipCrypto 加密:{info.filename}")
else:
raise
解 AES 加密 zip 的替代方案:pyminizip 或系统命令
如果确认是 AES 加密,最稳妥的方式是调用系统工具而非纯 Python 库。Python 生态中没有广泛维护、安全可靠的纯 Python AES-zip 解密实现(pyminizip 支持 AES 加密但不支持解密;py7zr 可解 AES-zip,但依赖较重且对某些 zip 兼容性差)。
推荐路径:
- Linux/macOS:用
unzip -P "password" archive.zip,捕获 stdout/stderr 判断失败 - Windows:用
tar -xf archive.zip --password=password(Win10 1803+ 内置 tar)或调用 7-Zip 命令行(7z x archive.zip -p"password") - 跨平台封装建议:用
subprocess.run(..., check=False),检查returncode和错误输出,避免静默失败
注意:密码含空格或特殊字符时,shell 调用需额外转义;更安全的做法是通过 stdin 输入密码(如 7-Zip 支持 -sccUTF-8 + echo "pwd" | 7z ...),但需确保目标环境支持。
密码编码与中文密码的坑
ZipCrypto 规范要求密码按 **IBM Code Page 437** 编码,而非 UTF-8。这意味着如果你的密码含中文或 emoji,"中文".encode() 得到的是 UTF-8 bytes,zipfile 却按 CP437 解码——结果必然失败。
实操建议:
- 尽量避免中文密码;若必须用,需手动转换:
"中文".encode('gbk').decode('cp437', errors='ignore').encode('cp437')(不保证通用,且极不可靠) - 更现实的做法:把中文密码转成拼音或英文缩写再试
- 所有测试务必用已知 ZipCrypto 加密的样本,不要拿随机下载的 zip 盲试
这个点极易被忽略——你可能密码没错、类型对了、代码也对了,就卡在编码上。

















