zipfile, tarfile

Zipなどの圧縮・展開用モジュール

7-Zip, WinRARなどの高速なアーカイバがインストール済なら、敢えてこれを使わなくてもsubprocess.run()でそちらを使った方が速いかも。

ただ、圧縮・展開にちょっと細かい条件をつけたい時には重宝。

Zip展開:新しいもののみ上書き

  • 展開先に同名の既存ファイルがあれば、更新時刻を比較し、新しければ上書き、同じか古ければスキップ
  • zipには、各ファイルの更新時刻が記録されている

from zipfile import ZipFile

src_path = 'src.zip'
tgt_dir = 'C:\\dst'

with ZipFile(src_path, mode='r') as zh:
    for zipinfo in zh.infolist():
        # zipアーカイブ内のファイルの更新時刻を取得
        zip_mtime = datetime.datetime(*zipinfo.date_time).timestamp()
        tgt_path = os.path.join(tgt_dir, zipinfo.filename)
        if os.path.exists(tgt_path):
            # 既存のファイルがあれば更新時刻を取得
            tgt_mtime = os.path.getmtime(tgt_path)
            # 既存の方が新しかったらスキップ
            if tgt_mtime >= zip_mtime:
                # 一応、ファイルサイズも出力しとく
                tgt_size = os.path.getsize(tgt_path)
                zip_size = zipinfo.file_size
                print(zipinfo.filename, 'already exists newer one.',
                      tgt_mtime, zip_mtime, tgt_size, zip_size)
                continue
        # 展開
        zh.extract(zipinfo, tgt_dir)
        # ファイル更新時刻とアクセス時刻を更新(そのままだと、展開時の時刻になる)
        os.utime(tgt_path, (zip_mtime, zip_mtime))
        print(zipinfo.filename, 'extracted.')

tgz展開: ファイル名などで選択して解凍

  • tarfile.open()で圧縮ファイルを読み込み開始
    • modeはrにしとけば、tar, tgz, tbzあたりは自動判定してくれる
  • TarFile.getmembers()で、圧縮ファイル中のファイルとディレクトリのTarInfoオブジェクトをイテレート
  • TarInfoオブジェクトは、name, size, mtime, isfile, isdirあたりの情報を持ってる
  • 解凍したいのがあったら、TarFile.extractfile(TarInfo) で そのファイルのio.BufferedReader オブジェクトが得られる
  • 解凍したい場所にバイナリ書き込みでopen()して書き込む

"""
tgzやtbzから、.dbファイルだけを解凍して抽出
"""

import tarfile
import os

gzip_path = 'tmp.tgz'
tgt_dir = 'extract'

def make_parent_dirs(path):
    pardir = os.path.dirname(path)
    if not os.path.exists(pardir):
        os.makedirs(pardir)

def main():
    if not os.path.exists(tgt_dir):
        os.makedirs(tgt_dir)
    
    with tarfile.open(gzip_path, mode='r') as rh:
        for mem in rh.getmembers():
            spn = mem.name.split('/')
            if spn[-1][-3:] != '.db':
                continue
            # print(mem)
            tgt_path = os.path.join(tgt_dir, mem.name)
            make_parent_dirs(tgt_path)
            with open(tgt_path, mode='wb') as wh:
                wh.write(rh.extractfile(mem).read())


if __name__ == '__main__':
    main()

programming/python/packages/zipfile.txt · 最終更新: 2018/02/16 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0