PKZIP ファイルは高度に構造化されており、末尾に追加するだけで問題が発生します。以前のバージョンが動作しているとは言えませんが、この問題の回避策は、読み取り用に zip ファイルを開き、書き込み用に新しいファイルを開き、最初の内容を抽出してから、最後に追加コンポーネントを追加することです。完了したら、元の zip ファイルを新しく作成したものに置き換えます。
コードを実行するときにコードを実行するときに取得するトレースバックは次のとおりです。
Traceback (most recent call last):
File "zip.py", line 19, in <module>
Foo()
File "zip.py", line 17, in Foo
print zip.read("bar")
File "/usr/lib/python2.6/zipfile.py", line 834, in read
return self.open(name, "r", pwd).read()
File "/usr/lib/python2.6/zipfile.py", line 874, in open
zinfo.orig_filename, fname)
zipfile.BadZipfile: File name in directory "bar" and header "foo" differ.
よく調べてみると、「a」は一般に読み取り可能ではないため、「a」追加モードで開かれたファイルのような StringIO から読み取っていることに気付きました。書いています。私はいくつかをだまして、これを更新するつもりです。
アップデート:
このコードのほとんどすべてを Doug Hellmann の優れたPython Module of the Weekから盗みましたが、期待どおりに機能することがわかりました。構造化された PKZIP ファイルに単純に追加することはできません。元の投稿のコードが機能したとしても、それは偶然でした:
import zipfile
import datetime
def create(archive_name):
print 'creating archive'
zf = zipfile.ZipFile(archive_name, mode='w')
try:
zf.write('/etc/services', arcname='services')
finally:
zf.close()
def print_info(archive_name):
zf = zipfile.ZipFile(archive_name)
for info in zf.infolist():
print info.filename
print '\tComment:\t', info.comment
print '\tModified:\t', datetime.datetime(*info.date_time)
print '\tSystem:\t\t', info.create_system, '(0 = Windows, 3 = Unix)'
print '\tZIP version:\t', info.create_version
print '\tCompressed:\t', info.compress_size, 'bytes'
print '\tUncompressed:\t', info.file_size, 'bytes'
print
zf.close()
def append(archive_name):
print 'appending archive'
zf = zipfile.ZipFile(archive_name, mode='a')
try:
zf.write('/etc/hosts', arcname='hosts')
finally:
zf.close()
def expand_hosts(archive_name):
print 'expanding hosts'
zf = zipfile.ZipFile(archive_name, mode='r')
try:
host_contents = zf.read('hosts')
finally:
zf.close
zf = zipfile.ZipFile(archive_name, mode='a')
try:
zf.writestr('hosts', host_contents + '\n# hi mom!')
finally:
zf.close()
def main():
archive = 'zipfile.zip'
create(archive)
print_info(archive)
append(archive)
print_info(archive)
expand_hosts(archive)
print_info(archive)
if __name__ == '__main__': main()
注目すべきは、への最後の呼び出しからの出力ですprint_info
。
...
hosts
Modified: 2010-05-20 03:40:24
Compressed: 404 bytes
Uncompressed: 404 bytes
hosts
Modified: 2010-05-27 11:46:28
Compressed: 414 bytes
Uncompressed: 414 bytes
既存の arcname 'hosts' に追加されず、追加のアーカイブ メンバーが作成されました。
「Je n'ai fait celle-ci plus longue que parce que je n'ai pas eu le loisir de la faire plus courte.」
-ブレーズ・パスカル