2010-05-27 15 views
5

Üzerinde çalıştığım bir programın bazı Python birim testlerinde uçtan uca testler için bellek içi zip dosyalarını kullanıyoruz. SetUp() 'da basit bir zip dosyası oluşturuyoruz, ancak bazı testlerde bazı arşivlerin üzerine yazmak istiyoruz. Bunun için "zip.writestr (archive_name, zip.read (archive_name) + new_content)" yazıyoruz.Python 2.6, zip dosyalarında varolan arşivlere eklenmek istemiyor

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() 

sorun gibi bir şey bu Python 2.4 ve 2.5 de çalışıyor olması, ancak değil 2.6. Python 2.6'da bu, baskı dosyasında "BadZipfile:" dizininde dosya adı "ve" foo "başlığının farklı olması ile başarısız oluyor.

Doğru dosya çubuğunu okuyormuş gibi görünüyor, ancak bunun yerine foo okuması gerektiğini düşünüyor.

Kaybettim. Neyi yanlış yapıyorum? Bu desteklenmiyor mu? İnternette arama yapmayı denedim, ancak benzer sorunlardan bahsetmedim. Ben zip dosyası belgelerini okudum, ancak (aslında) olduğunu düşündüğüm bir şey bulamadım, özellikle read() ile dosya adı dizesini çağırdığımdan.

Herhangi bir fikrin var mı?

şimdiden teşekkür ederiz!

cevap

2

PKZIP dosyası son derece yapılandırılmıştır ve yalnızca sonuna kadar eklemek bu sorunu çözecektir. Daha önceki sürümlerle çalışamıyorum, ancak bu soruna yönelik çözüm okumak için bir zip dosyası açmak, yazmak için yeni bir tane açmak, ilk önce içeriği açmak ve sonra ek bileşenlerinizi sonuna eklemek. Tamamlandığında, yeni oluşturulan ile orijinal zipfile değiştirin.

kodunuzu çalıştırırken kodunuzu çalıştırırken alıyorum traceback geçerli:

yakından baktığınızda
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. 

, sana bir dosya benzeri StringIO okuyor olduğunuzu fark 'a'ppend modu ile açılan hangi should 'a' genel olarak okunamadığından ve okumalar ile yazmalar arasında mutlaka aranması gerektiğinden okuma hatasıyla sonuçlanır. Bazılarını kandıracağım ve bunu güncelleyeceğim.

Güncelleme:

hemen hemen tüm Doug Hellmann mükemmel Python Module of the Week bu kodun, ben beklediğim gibi hemen hemen çalıştığını bulmak çalıntı olması. Bir yalnızca yapılandırılmış PKZIP dosyasına eklenecek olamaz ve orijinal sonrası kod hiç çalışma yaptı, eğer kazara oldu:

... 
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 
: print_info için

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() 

Önemli geçen çağrısından çıkışı

Mevcut arcname 'hosts'lerine eklenmedi, ek bir arşiv üyesi oluşturdu.

"Je n'ai fait celle-ci artı longue que parce que je n'ai eu le loisir de la faire artı Courte pas."
- Blaise Pascal

0

ZIP dosyası formatı eklenecek şekilde tasarlanmıştır.Aynı ada sahip ek dosyalar ekleyebilir ve sonuncuyu çıkarır, ancak ZipFile aynı anda okumak ve yazmak için tasarlanmamıştır. Daha sonra open() veya read() yöntemiyle yeniden okunan son kayıtları (https://hg.python.org/cpython/file/2.7/Lib/zipfile.py#l1263) yazmak için dosyayı kapatmanız gerekir. (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() 

Çıkış:

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