Python 2.6 does not like adding existing archives to zip files

In some of the Python unit tests I'm working on, we use in-memory zip files for end tests. In SetUp (), we create a simple zip file, but in some tests we want to overwrite some archives. To do this, we do "zip.writestr (archive_name, zip.read (archive_name) + new_content)". Sort of

import zipfile
from StringIO import StringIO

def Foo():
    zfile = StringIO()
    zip = zipfile.ZipFile(zfile, 'a')
    zip.writestr(
        "foo",
        "foo content")
    zip.writestr(
        "bar",
        "bar content")
    zip.writestr(
        "foo",
        zip.read("foo") +
        "some more foo content")
    print zip.read("bar")

Foo()

The problem is that this works fine in Python 2.4 and 2.5, but not 2.6. In Python 2.6, this fails on the print line with "BadZipfile: the file name in the directory" bar ", and the header" foo "is different."

It seems that he is reading the correct line with the files, but believes that he should read foo instead.

. ? ? , . zipfile, - (, , ), , read() .

?

!

+5
2

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.

, StringIO, "append", , "a" , , seek() ed . .

Update:

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

"host" arcname, .

"Je n'ai fait celle-ci plus longue que parce que je n'ai pas eu le loisir de la faire plus courte."
-

+2

ZIP . , ZipFile . (https://hg.python.org/cpython/file/2.7/Lib/zipfile.py#l1263), open() read() . (https://hg.python.org/cpython/file/2.7/Lib/zipfile.py#l933)

import zipfile
from StringIO import StringIO

def Foo():
    zfile = StringIO()

    zip = zipfile.ZipFile(zfile, 'a')
    zip.writestr(
        "foo",
        "foo content")
    zip.writestr(
        "bar",
        "bar content")
    zip.close()

    zip = zipfile.ZipFile(zfile, 'r')
    foo_content = zip.read("foo")

    zip2 = zipfile.ZipFile(zfile, 'a')
    zip2.writestr(
        "foo",
        foo_content +
        "some more foo content")
    print zip2.namelist()
    print zip2.read("bar")

Foo()

:

pyzip.py:23: UserWarning: Duplicate name: 'foo'
  "some more foo content")
['foo', 'bar', 'foo']
bar content
0

All Articles