2010-05-27 31 views
5

Trong một số bài kiểm tra đơn vị Python của chương trình tôi đang làm việc, chúng tôi sử dụng tệp zip trong bộ nhớ cho các bài kiểm tra đầu cuối. Trong SetUp(), chúng tôi tạo một tệp zip đơn giản, nhưng trong một số thử nghiệm, chúng tôi muốn ghi đè lên một số lưu trữ. Đối với điều này chúng tôi làm "zip.writestr (archive_name, zip.read (archive_name) + new_content)". Một cái gì đó nhưPython 2.6 không thích thêm vào lưu trữ hiện tại trong các tệp zip

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

Vấn đề là điều này hoạt động tốt trong Python 2.4 và 2.5, nhưng không 2.6. Trong Python 2.6 điều này không thành công trên dòng in với "BadZipfile: Tên tệp trong thư mục" thanh "và tiêu đề" foo "khác nhau."

Dường như nó đang đọc đúng thanh tệp nhưng thay vào đó nó cho rằng nó nên đọc foo.

Tôi đang thua lỗ. Tôi đang làm gì sai? Điều này có được hỗ trợ không? Tôi đã thử tìm kiếm trên web nhưng không thể đề cập đến vấn đề tương tự. Tôi đọc các tài liệu zipfile, nhưng không thể tìm thấy bất cứ điều gì (mà tôi nghĩ là) có liên quan, đặc biệt là kể từ khi tôi đang gọi đọc() với chuỗi tên tập tin.

Bất kỳ ý tưởng nào?

Cảm ơn bạn trước!

Trả lời

2

Tệp PKZIP có cấu trúc cao và chỉ nối thêm vào cuối sẽ làm hỏng lên. Tôi không thể nói với các phiên bản trước đó, nhưng giải pháp cho vấn đề này là mở một tệp zip để đọc, mở một tệp mới để viết, trích xuất nội dung đầu tiên và sau đó thêm các thành phần bổ sung của bạn vào cuối. Khi hoàn thành, hãy thay thế tệp zip gốc bằng tệp zip mới được tạo.

Các traceback tôi nhận được khi chạy mã của bạn khi chạy mã của bạn là:

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. 

Sau khi kiểm tra chặt chẽ hơn, tôi nhận thấy rằng bạn đang đọc từ một tập tin giống như StringIO mở với 'chế độ a'ppend mà nên kết quả trong một lỗi đọc vì 'a' không thể đọc được, và chắc chắn phải tìm kiếm() ed giữa các lần đọc và viết. Tôi sẽ đánh lừa một số và cập nhật điều này.

Cập nhật:

Sau khi bị đánh cắp khá nhiều tất cả các mã này từ Doug Hellmann của tuyệt vời Python Module of the Week, tôi thấy rằng nó hoạt động khá nhiều như tôi mong đợi. Người ta có thể không chỉ đơn thuần là thêm vào một tập tin PKZIP có cấu trúc, và nếu mã trong các bài bản gốc bao giờ đã làm việc, đó là một cách tình cờ:

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

đáng chú ý là sản phẩm từ các cuộc gọi cuối cùng để 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 

Nó không gắn thêm vào 'tên máy chủ' hiện có, nó tạo ra một thành viên lưu trữ bổ sung.

"Je n'ai fait celle-ci cộng longue que parce que je n'ai pas le eu Loisir de la faire cộng courte."
- Blaise Pascal định dạng file

0

Các bưu điện được thiết kế để gắn vào.Nó có thể thêm các tệp bổ sung có cùng tên và sẽ trích xuất tệp cuối cùng, nhưng ZipFile không được thiết kế để đọc và ghi cùng một lúc. Bạn phải đóng tệp để ghi lại các bản ghi cuối (https://hg.python.org/cpython/file/2.7/Lib/zipfile.py#l1263) sau đó được đọc lại bằng phương thức open() hoặc 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() 

Output:

pyzip.py:23: UserWarning: Duplicate name: 'foo' 
    "some more foo content") 
['foo', 'bar', 'foo'] 
bar content 
Các vấn đề liên quan