创建 zip 文件

demo

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import zipfile
from pathlib import Path

with zipfile.ZipFile('/mnt/e/Downloads/hello.zip', 'w') as zfile:
    # zfile.writestr('/path/to/zip/insidefile.txt', "content_str_or_bytes")
    zfile.writestr('folder/age.txt', "12") # 写入 str 类型
    zfile.writestr('raw', "好天气".encode()) # 写入 bytes 类型
    zfile.writestr('demo/qq.exe', Path('/mnt/e/Downloads/qq.exe').read_bytes())

    # 直接写入文件,不需要通过 open 读入内存再写入zip
    zipfile.write("/file/on/disk.txt", "path/in/zipfile/name.txt")

遍历 zip 文件

使用 ZipFile.infolist()

使用 ZipFile.namelist()

1
2
3
4
In [22]: with zipfile.ZipFile('/mnt/e/Downloads/hello.zip', 'r') as zread:
    ...:     print(zread.filelist)
    ...:
[<ZipInfo filename='folder/age.txt' filemode='?rw-------' file_size=2>, <ZipInfo filename='raw' filemode='?rw-------' file_size=9>, <ZipInfo filename='demo/qq.exe' filemode='?rw-------' file_size=183394032>]

使用 ZipFile.filelist 属性

1
2
3
4
In [24]: with zipfile.ZipFile('/mnt/e/Downloads/hello.zip', 'r') as zread:
    ...:     print(zread.namelist())
    ...:
['folder/age.txt', 'raw', 'demo/qq.exe']

使用 zipfile.Path 类 (类似 pathlib.Path)

1
2
3
4
5
In [25]: list(zipfile.Path('/mnt/e/Downloads/hello.zip', at='/').iterdir())
Out[25]:
[Path('/mnt/e/Downloads/hello.zip', 'raw'),
 Path('/mnt/e/Downloads/hello.zip', 'folder/'),
 Path('/mnt/e/Downloads/hello.zip', 'demo/')]

递归遍历:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from pathlib import Path

import zipfile

def zipiter_recursive(filename: Path|str):
    if isinstance(filename, (Path, str)):
        zip_file = Path(filename)
        assert zip_file.suffix.lower() == ".zip"
        iter_path = zipfile.Path(zip_file)

    elif isinstance(filename, zipfile.Path):
        iter_path = filename
    else:
        raise TypeError(f'not a valid zip file {filename = }')

    for i in iter_path.iterdir():
        if i.is_dir():
            yield from zipiter_recursive(i)
        else:
            yield i

使用例子:

1
2
3
4
5
In [3]: list(zipiter_recursive('/mnt/e/Downloads/hello.zip'))
Out[3]:
[Path('/mnt/e/Downloads/hello.zip', 'raw'),
 Path('/mnt/e/Downloads/hello.zip', 'folder/age.txt'),
 Path('/mnt/e/Downloads/hello.zip', 'demo/qq.exe')]

zipfile.Path

创建:

  1. 通过 .zip 文件: Path("/path/to/demo.zip", "a/b.txt")
  2. 通过 zipfile.ZipFile 创建: Path(zipfile.ZipFie("/path//to/demo.zip"))

功能:

  1. 遍历文件: Path.iterdir()
  2. 获取 pathlib.Path 路径对象: Path.filename 属性
  3. 获取在 zip 文件中的保存路径,利用 zipfile.Path.filename 实现:

    1
    2
    3
    4
    5
    6
    7
    8
    
    In [13]: p
    Out[13]: Path('/mnt/e/Downloads/hello.zip', 'folder/age.txt')
    
    In [14]: p.filename
    Out[14]: PosixPath('/mnt/e/Downloads/hello.zip/folder/age.txt')
    
    In [15]: p.filename.relative_to(p.root.filename)
    Out[15]: PosixPath('folder/age.txt')
  4. 路径拼接: Path.joinpath()

    • 支持: zipfile.Path.joinpath(pathlib.Path)
    • 支持: zipfile.Path.joinpath(str_filepath)

zipfile.ZipInfo

  1. 创建方法:

    • ZipFile.getinfo(name)

      • 已有的 .zip 文件读取时使用
    • ZipInfo.from_file(file_to_save, filename_in_archieve)

      • 创建一个新的 .zip 文件时使用
    • ZipInfo(archive_name, date_time=…)
    • 使用 zipfile.Path 获取

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      
      import zipfile
      from pathlib import Path
      
      
      zfile_path = "/path/to/my.zip"
      with zipfile.ZipFile() as sub_zfile:
          for file in zipfile.Path(zfile_path).iterdir():
              file_arc_path = (
                  Path(Path(name).stem)
                  .joinpath(file.filename.relative_to(file.root.filename))
                  .as_posix()
              )
              file_zinfo = sub_zfile.getinfo(
                  file.filename.relative_to(file.root.filename).as_posix()
              )
              print(file_zinfo)
  2. 用途:

    • 读取压缩文件的更多信息

      • 时间
      • 大小
      • 压缩大小
    • 创建.zip 时,创建和自定义压缩文件的信息