2010-05-27 3 views
5

프로그램의 일부 Python 유닛 테스트에서 엔드 투 엔드 테스트를 위해 메모리 내장 zip 파일을 사용합니다. SetUp()에서는 간단한 zip 파일을 만들지 만 일부 테스트에서는 일부 아카이브를 덮어 쓰려고합니다. 이를 위해 "zip.writestr (archive_name, zip.read (archive_name) + new_content)"를 수행합니다.Python 2.6은 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() 

문제와 같은 뭔가이 파이썬 2.4과 2.5에서 잘 작동하지만, 하지 2.6. 파이썬 2.6에서 이것은 "BadZipfile : 디렉토리"bar "의 파일 이름과 헤더"foo "가 다른 인쇄 줄에서 실패합니다."

올바른 파일 막대를 읽는 것 같지만 대신 foo를 읽어야한다고 생각합니다.

나는 손실에 처해있다. 내가 도대체 ​​뭘 잘못하고있는 겁니까? 지원되지 않습니까? 웹 검색을 시도했지만 유사한 문제에 대한 언급은 찾을 수 없습니다. 나는 zipfile 문서를 읽었지만 관련이 있다고 생각되는 항목을 찾지 못했습니다. 특히 filename 문자열로 read()를 호출 한 이후입니다.

아이디어가 있으십니까?

미리 감사드립니다.

답변

2

PKZIP 파일은 고도로 구조화되어 있으며 마지막 부분 만 첨부하면됩니다. 이전 버전의 작업에 대해서는 말할 수 없지만이 문제의 해결 방법은 읽기 용으로 zip 파일을 열고 작성 용으로 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에서 읽고있는 것을 알 'a'ppend 모드를 오픈하는해야 'a'는 일반적으로 읽을 수 없으므로 읽기 오류가 발생하며 읽기 및 쓰기 사이에서 반드시 seek()되어야합니다. 나는 바보짓을하고 이것을 업데이트 할 것입니다.

업데이트 :

는 거의 모든 덕 헬만의 우수한 Python Module of the Week에서이 코드의, 나는 그것이 내가 예상대로 거의 작동 찾을 도난 가졌어요. 하나는 단순히 구조화 PKZIP 파일에 추가 할 수 없습니다, 그리고 원래의 게시물의 코드가 이제까지 일을했다면, 그것은 우연이었다

... 
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

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

주목할만한 마지막 호출의 출력

기존 호 이름 'hosts'에 추가하지 않았으므로 추가 아카이브 멤버가 생성됩니다.

"이인제 n'ai 기정 첼레-CI 플러스의 자 케 PARCE 케 이인제 n'ai 유럽 연합 (EU) 르와 지르 드 라 방임 플러스 courte 싶어서."
- 블 레즈 파스칼

0

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 
관련 문제