2017年11月19日日曜日

Python3でzipアーカイブ内のファイルを更新する

Pythonでのzipアーカイブの扱いは標準ライブラリのzipfileでできる。解凍や作成、アーカイブ内のファイルの参照ができるが、アーカイブ内のファイルを更新するメソッドなどは用意されていない。実際に更新する方法を調べたのでまとめておく。


OSはRaspbian Jessie。



まずは「hello.txt」「readme.txt」「contents.txt」という3つのテキストファイルを含む「archive.zip」とういアーカイブを作成する。
import zipfile

# zipアーカイブの作成
with zipfile.ZipFile('archive.zip', 'w', zipfile.ZIP_DEFLATED) as af:
    af.writestr('hello.txt', 'Hello!')
    af.writestr('readme.txt', 'Please read me!')
    af.writestr('contents.txt', '隣の客はよく柿食う客だ')

# 作成したzipアーカイブ内のファイル内容の出力
with zipfile.ZipFile('archive.zip', 'r') as rf:
    for item in rf.infolist():
        print(item.filename, rf.read(item.filename).decode('utf-8'))

上記コードを実行すると以下の結果が出力される。



zipfileのドキュメントを見るとwritestrではファイルの追加はできるようなので、「archive.zip」内の「contents.txt」を更新してみる。
import zipfile

# zipアーカイブの更新
with zipfile.ZipFile('archive.zip', 'a') as uf:
    uf.writestr('contents.txt', '東京特許許可局')

# zipアーカイブ内のファイル内容の出力
with zipfile.ZipFile('archive.zip', 'r') as rf:
    for item in rf.infolist():
        print(item.filename, rf.read(item.filename).decode('utf-8'))

上記コードを実行すると以下の様なメッセージが出力され、「contents.txt」が2つになってしまっている。



ではどうするかというと、How to update one file inside zip file using python [duplicate]にあるように、既存のzipアーカイブ内のファイルをコピーして、新たなアーカイブを作成する。そのときに更新するファイルだけコピーせずに新規作成する。
import zipfile

# zipアーカイブ内のファイル更新
with zipfile.ZipFile('archive.zip', 'r') as inf, \
    zipfile.ZipFile('archive_new.zip', 'w', zipfile.ZIP_DEFLATED) as outf:

    for item in inf.infolist():
        if (item.filename != 'contents.txt'):
            outf.writestr(item, inf.read(item.filename))
        else:
            outf.writestr('contents.txt', '東京特許許可局')

# 作成したzipアーカイブ内のファイル内容の出力
with zipfile.ZipFile('archive_new.zip', 'r') as rf:
    for item in rf.infolist():
        print(item.filename, rf.read(item.filename).decode('utf-8'))

上記コードを実行すると、contents.txtが2つになることはなく、中身は元々あるファイルからちゃんと変わっている。


0 件のコメント:

コメントを投稿