此代碼是在通過HTTP多部分POST接收上傳的zip文件並不會只讀內部的數據的處理的Django應用程序的代碼簡化:奇怪「BadZipfile:壞CRC-32」的問題
#!/usr/bin/env python
import csv, sys, StringIO, traceback, zipfile
try:
import io
except ImportError:
sys.stderr.write('Could not import the `io` module.\n')
def get_zip_file(filename, method):
if method == 'direct':
return zipfile.ZipFile(filename)
elif method == 'StringIO':
data = file(filename).read()
return zipfile.ZipFile(StringIO.StringIO(data))
elif method == 'BytesIO':
data = file(filename).read()
return zipfile.ZipFile(io.BytesIO(data))
def process_zip_file(filename, method, open_defaults_file):
zip_file = get_zip_file(filename, method)
items_file = zip_file.open('items.csv')
csv_file = csv.DictReader(items_file)
try:
for idx, row in enumerate(csv_file):
image_filename = row['image1']
if open_defaults_file:
z = zip_file.open('defaults.csv')
z.close()
sys.stdout.write('Processed %d items.\n' % idx)
except zipfile.BadZipfile:
sys.stderr.write('Processing failed on item %d\n\n%s'
% (idx, traceback.format_exc()))
process_zip_file(sys.argv[1], sys.argv[2], int(sys.argv[3]))
很簡單。我們在zip文件中打開zip文件和一個或兩個CSV文件。
有什麼奇怪的是,如果我跑這一個大的zip文件(〜13 MB),並有它比一個普通的文件名以外的StringIO.StringIO
或io.BytesIO
(也許任何實例化ZipFile
?我在Django的類似問題嘗試通過TemporaryUploadedFile
創建ZipFile
或通過調用os.tmpfile()
和shutil.copyfileobj()
創建文件對象時創建應用程序),並打開兩個csv文件而不是一個,然後在處理結束時失敗。下面是我在Linux系統上看到的輸出:
$ ./test_zip_file.py ~/data.zip direct 1
Processed 250 items.
$ ./test_zip_file.py ~/data.zip StringIO 1
Processing failed on item 242
Traceback (most recent call last):
File "./test_zip_file.py", line 26, in process_zip_file
for idx, row in enumerate(csv_file):
File ".../python2.7/csv.py", line 104, in next
row = self.reader.next()
File ".../python2.7/zipfile.py", line 523, in readline
return io.BufferedIOBase.readline(self, limit)
File ".../python2.7/zipfile.py", line 561, in peek
chunk = self.read(n)
File ".../python2.7/zipfile.py", line 581, in read
data = self.read1(n - len(buf))
File ".../python2.7/zipfile.py", line 641, in read1
self._update_crc(data, eof=eof)
File ".../python2.7/zipfile.py", line 596, in _update_crc
raise BadZipfile("Bad CRC-32 for file %r" % self.name)
BadZipfile: Bad CRC-32 for file 'items.csv'
$ ./test_zip_file.py ~/data.zip BytesIO 1
Processing failed on item 242
Traceback (most recent call last):
File "./test_zip_file.py", line 26, in process_zip_file
for idx, row in enumerate(csv_file):
File ".../python2.7/csv.py", line 104, in next
row = self.reader.next()
File ".../python2.7/zipfile.py", line 523, in readline
return io.BufferedIOBase.readline(self, limit)
File ".../python2.7/zipfile.py", line 561, in peek
chunk = self.read(n)
File ".../python2.7/zipfile.py", line 581, in read
data = self.read1(n - len(buf))
File ".../python2.7/zipfile.py", line 641, in read1
self._update_crc(data, eof=eof)
File ".../python2.7/zipfile.py", line 596, in _update_crc
raise BadZipfile("Bad CRC-32 for file %r" % self.name)
BadZipfile: Bad CRC-32 for file 'items.csv'
$ ./test_zip_file.py ~/data.zip StringIO 0
Processed 250 items.
$ ./test_zip_file.py ~/data.zip BytesIO 0
Processed 250 items.
順便說一下,代碼相同的條件下,但在我的OS X系統上的不同的方式失敗。而不是BadZipfile
異常,它似乎讀取損壞的數據並變得非常困惑。
這一切都暗示我在做這個代碼中你不應該做的事 - 例如:在文件上調用zipfile.open
,同時已經在同一個zip文件對象中打開另一個文件?這在使用ZipFile(filename)
時似乎沒有問題,但由於zipfile
模塊中的某些實現細節,在傳遞ZipFile
類似文件的對象時可能會出現問題?
也許我錯過了zipfile
文檔中的內容?或者,也許它還沒有記錄?或者(最不可能),zipfile
模塊中的錯誤?
我剛剛發現的這一提的我在某種程度上忽略了之前的Python文檔。 – 2011-04-11 21:49:37
我遇到了同樣的問題。相同的代碼在Python2中產生了錯誤,但在Python3中產生了錯誤。所以我根據這裏的解決方案嘗試,傳遞一個文件名而不是文件對象。然後我遇到了'打開太多文件'的錯誤,如果zip有數百個成員,就會發生這種情況。然後我意識到,如果我在初始化ZipFile之前對文件對象執行seek(0),錯誤就會消失。不明白爲什麼,因爲我之前在文件對象上什麼也沒做... – deeenes 2016-06-29 19:53:38