2013-06-25 108 views
1

我試圖在Python中創建內存中的zip文件並將其上傳到Amazon S3。我已經閱讀了關於此事的類似帖子,但無論我嘗試什麼,Windows和Linux(RHEL5)都無法打開它(它已損壞)。下面是我運行代碼:內存中的Zip文件Python錯誤

f_redirects = StringIO() 
f_links = StringIO() 
f_metadata = StringIO() 

# Write to the "files" 

zip_file = StringIO() 
zip = zipfile.ZipFile(zip_file, 'a', zipfile.ZIP_DEFLATED, False) 
zip.writestr('redirects.csv', f_redirects.getvalue()) 
zip.writestr('links.csv', f_bad_links.getvalue()) 
zip.writestr('metadata.csv', f_metadata.getvalue()) 

f_redirects.close() 
f_links.close() 
f_metadata.close() 

k = Key(BUCKET) 
k.key = '%s.zip' % base_name 
k.set_metadata('Content-Type', 'application/zip') 
k.set_contents_from_string(zip_file.getvalue()) 
zip.close() 
zip_file.close() 
+0

首先,您是否試過在本地保存'.zip'文件並打開它,以查看問題與S3是否有關係? – abarnert

回答

5

的問題是,你想,你就可以打電話close前使用ZipFile的內容。

由於the documentation說:

必須調用close() ...或必要記錄將不被寫入。

最重要的是,雖然它有時可行,但在關閉的StringIO上調用getvalue()實際上是不合法的。再次,從the docs

返回一個包含緩衝的全部內容在StringIO對象的close()方法之前的任何時間str被調用。

最後,如果您使用的是Python 3.x,則可能需要使用BytesIO而不是StringIO。事實上,只要你使用2.6+,你甚至可以在2.x中使用BytesIO


而且,你的代碼將是一個很大的可讀性,而且很難得到錯誤的,如果你使用with語句,而不是手動試圖close的事情,並沒有嘗試在頂部「聲明變量「C-風格:

with BytesIO() as zip_file: 
    with zipfile.ZipFile(zip_file, 'a', zipfile.ZIP_DEFLATED, False) as zip: 
     zip.writestr('redirects.csv', f_redirects.getvalue()) 
     zip.writestr('links.csv', f_bad_links.getvalue()) 
     zip.writestr('metadata.csv', f_metadata.getvalue()) 
    zip_contents = zip_file.getvalue() 

k = Key(BUCKET) 
k.key = '%s.zip' % base_name 
k.set_metadata('Content-Type', 'application/zip') 
k.set_contents_from_string(zip_contents) 

如果你正在使用Python 2.x中,並希望留在StringIO,它不是直接可用作上下文管理器,所以你必須更換第一線與:

with contextlib.closing(StringIO()) as zip_file: 
+0

感謝您的幫助! –