Skip to content

zipfile

zipfile库提供了对 zip 归档文件的不完整支持,他不能处理 zip 分卷,不支持创建加密 zip 文件(支持解密)。

ZipFile

该库使用 ZipFile() 来构造一个 zip 对象,他支持 with 语句:

Python
class zipfile.ZipFile(
    file,    # path-like object
    mode='r',# r - 读取  w - 写入新文件(如果存在则覆盖) a - 像现有文件中添加 x - 写入新文件(文件存在抛出异常)
    compression=ZIP_STORED, # 压缩算法 ZIP_STORED 仅归档 ZIP_DEFLATED (zlib提供) ZIP_BZIP2(bz2提供) ZIP_LZMA(lzma提供) 有些压缩软件并不支持后两个
    allowZip64=True, # 是否支持 4G 以上的归档文件
    compresslevel=None, # 压缩等级 0~9
    strict_timestamps=True, # zip 时间戳精度有问题,仅支持 1980-1-1 ~ 2107-12-31 如果设置为 False 其他时间戳的文件会强制转换为这个时间范围内,默认 True 时间戳外的文件会报错
    metadata_encoding=None # 元信息编码
):
    pass

最终会返回一个 ZipFile 对象,他代表一个 zip 归档文件,我们操作这个 ZipFile 对象无非就是进行增删改查,最后 ZipFile.close() 即可(如果使用 with 语句不需要我们手动处理它):

  • ZipFile.namelist(): 返回按照名称排序的归档成员
  • ZipFile.infolist(): 返回 zip 文件中的每个成员的 ZipInfo 对象
  • ZipFile.getinfo(name): 返回指定文件的 ZipInfo 对象
  • ZipFile.open(name, mode='r'): 打开 zip 归档文件中的指定文件(open 接口),如果 mode='w' 支持写入,需要注意当写入时无法再读写这个 ZipFile 对象直到写入完成
  • ZipFile.read(name): 读取指定文件,open() 的 read 接口(如果需要流式读取还是需要 open)
  • ZipFile.write(filename, arcname=None): 将名为 filename 的文件写入到 zip 归档文件中,文件名为 arcname(默认为 filename 去除盘符和开头的路径分隔符)。它实际上就是open(filename, 'r')之后ZipFile.open(arcname).write()的便捷方法
  • ZipFile.writestr(arcname, data: str|bytes): 实际上就是 ZipFile.open(arcname).write(data) 的便捷方法
  • ZipFile.extract(member, path=None): 从 zip 归档文件中提取一个文件,默认当前目录
  • ZipFile.extractall(path=None): 从 zip 归档文件中提取所有文件, 默认当前目录
  • ZipFile.mkdir(zinfo_or_dir): 在归档文件内创建一个目录

ZipInfo

上面所有需要指定 zip 归档中文件的地方都可以是一个路径字符串(没有盘符和开头的路径分隔符),例如 open 中的 name、write 中的 arcname 和 extract 中的 member。实际上他们还可以是一个 ZipInfo 对象,这个对象代表 zip 归档中的每个文件,要构造这个对象有两种方法:

  1. ZipInfo.from_file(filename, arcname=None) : 为文件系统的文件构造一个 ZipInfo 实例,供ZipFile.write()方法使用将在随后添加到 zip 归档中
  2. ZipFile.getinfo()ZipFile.infolist(): 这两个方法都能够返回ZipInfo对象

Tips

文件夹本身也存在一个 ZipInfo 对象,因此这个对象更像是一个节点对象

ZipInfo 对象包含以下实例:

  • ZipInfo.is_dir(): 是否是文件夹
  • ZipInfo.filename: 归档中的文件名称
  • ZipInfo.compress_size: 已压缩的文件大小
  • ZipInfo.file_size: 原始文件的大小

Path

zip 归档可以看作是一个小型的文件系统,Python 使用 pathlib.Path 一样的接口来为 ZipFile 构造一个 Path 对象:

Python
class zipfile.Path(
    root, # 可以是 ZipFile 实例,或者 zip 文件路径
    at="" # 指定相对路径,默认是根目录,即 root/dir1/file1.txt root/file2.txt
):
    pass

Path 暴露出来的接口是 pathlib.Path 的子集:

  • Path.name: 路径名称
  • Path.is_dir(): 是否是文件夹
  • Path.is_file(): 是否是文件
  • Path.iterdir(): 迭代文件夹下文件
  • Path.exists(): 文件/文件夹是否存在
  • Path.suffix: 文件后缀名
  • Path.stem: 排除后缀名的路径
  • Path.open(mode='r'): 打开文件
  • Path.read_text(): 读取文本文件
  • Path.read_bytes(): 读取二进制文件

Path 在对 zip 进行读写操作的时候非常有用,他将 zip 当作一个独立的文件系统提供了 pathlib 一样的操作接口,他屏蔽了 zip 和本地系统的区别:

Python
import zipfile

with zipfile.ZipFile("test.zip", "w", compression=zipfile.ZIP_DEFLATED) as zip_file:
    path = zipfile.Path(zip_file)
    (path / "test1.txt").open("w").write("test1")
    (path / "test2.txt").open("w").write("test2")
    (path / "inner" / "inner1.txt").open("w").write("inner1")
    (path / "inner" / "inner2.txt").open("w").write("inner2")