ZipFile.testzip文件()在python2和python3上返回不同的结果

2024-10-04 05:25:36 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中使用zipfile模块解压缩大数据文件在Python 2上可以正常工作,但是在python3.6.0上会产生以下错误:

BadZipFile: Bad CRC-32 for file 'myfile.csv'

我追踪到错误处理代码检查CRC值。在

在python2上使用ZipFile.testzip()不会返回任何结果(所有文件都很好)。在Python3上运行它会返回'myfile.csv',表示该文件有问题。在

要在Python2和Python3上复制的代码(需要下载300 MB,抱歉):

import zipfile
import urllib
import sys

url = "https://de.iplantcollaborative.org/anon-files//iplant/home/shared/commons_repo/curated/Vertnet_Amphibia_Sep2016/VertNet_Amphibia_Sept2016.zip"

if sys.version_info >= (3, 0, 0):
    urllib.request.urlretrieve(url, "vertnet_latest_amphibians.zip")
else:
    urllib.urlretrieve(url, "vertnet_latest_amphibians.zip")

archive = zipfile.ZipFile("vertnet_latest_amphibians.zip")
archive.testzip()

有人知道为什么会有这种差异吗?有没有办法让Python 3使用以下方法正确地提取文件:

^{pr2}$

Tags: 文件csv代码importurlurllibzipmyfile
3条回答

与@Kundor一样,将文件大小设置为最大值(2**32-1)将有效,但对于任何大于4 GiB(4 GiB减去1字节)的文件,将其设置为ZIP64的最大大小(16 EiB减去1字节)

在(927MB压缩和11GB文件提取)上测试

url: https://de.iplantcollaborative.org/anon-files//iplant/home/shared/commons_repo/curated/Vertnet_Aves_Sep2016/VertNet_Aves_Sept2016.zip

file: vertnet_latest_birds.csv

import zipfile
import urllib
import sys

url = "https://de.iplantcollaborative.org/anon-files//iplant/home/shared/commons_repo/curated/Vertnet_Amphibia_Sep2016/VertNet_Amphibia_Sept2016.zip"
zip_path = "vertnet_latest_amphibians.zip"
file_to_extract = "vertnet_latest_amphibians.csv"

if sys.version_info >= (3, 0, 0):
    urllib.request.urlretrieve(url, zip_path)
else:
    urllib.urlretrieve(url, zip_path)

archive = zipfile.ZipFile(zip_path)
if archive.testzip():
    # reset uncompressed size header values to maximum
    archive.getinfo(file_to_extract).file_size += (2 ** 64) - 1

open_archive_file = archive.open(file_to_extract, 'r')
# or archive.extract(file_to_extract)

CRC值正常。最新的CRC_两栖动物.csv'在zip中记录的是0x87203305。提取后,这确实是文件的CRC。在

但是,给定的未压缩大小是不正确的。压缩文件记录的压缩大小为309723024字节,未压缩大小为292198614字节(更小!)。实际上,未压缩的文件是4587165910字节(4.3gib)。这比32位计数器中断时的4 GiB阈值大。在

您可以这样修复(这至少在python3.5.2中有效):

archive = zipfile.ZipFile("vertnet_latest_amphibians.zip")
archive.getinfo("vertnet_latest_amphibians.csv").file_size += 2**32
archive.testzip() # now passes
archive.extract("vertnet_latest_amphibians.csv") # now works

我无法从归档文件中提取python3。一些调查结果(在macosx上)可能会有帮助。在

检查档案的运行状况

将文件设为只读,以防止意外更改:

$ chmod -w vertnet_latest_amphibians.zip 
$ ls -lh vertnet_latest_amphibians.zip 
-r r r  1 lawh 2045336417 296M Jan  6 10:10 vertnet_latest_amphibians.zip

使用zipunzip检查存档:

^{pr2}$

@sam mussmann也发现,7z报告了一个CRC错误:

$ 7z t vertnet_latest_amphibians.zip 

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,4 CPUs x64)

Scanning the drive for archives:
1 file, 309726398 bytes (296 MiB)

Testing archive: vertnet_latest_amphibians.zip
 
Path = vertnet_latest_amphibians.zip
Type = zip
Physical Size = 309726398

ERROR: CRC Failed : vertnet_latest_amphibians.csv

Sub items Errors: 1

Archives with Errors: 1

Sub items Errors: 1

我的zipunzip都很老;7z很新:

$ zip -v | head -2
Copyright (c) 1990-2008 Info-ZIP - Type 'zip "-L"' for software license.
This is Zip 3.0 (July 5th 2008), by Info-ZIP.

$ unzip -v | head -1
UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.

$ 7z  help |head -3

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,4 CPUs x64)

摘录

使用unzip

$ time unzip vertnet_latest_amphibians.zip vertnet_latest_amphibians.csv
Archive:  vertnet_latest_amphibians.zip
  inflating: vertnet_latest_amphibians.csv  

real    0m17.201s
user    0m14.281s
sys 0m2.460s

使用Python 2.7.13进行提取,为简洁起见,使用zipfile的命令行界面:

$ time ~/local/python-2.7.13/bin/python2 -m zipfile -e vertnet_latest_amphibians.zip .

real    0m19.491s
user    0m12.996s
sys 0m5.897s

正如您所发现的,python3.6.0(也是3.4.5和3.5.2)报告了一个错误的CRC

假设1:档案包含一个错误的CRC,zipunzip并且 Python2.7.13无法检测;7z和python3.4-3.6都在执行 没错。在

假设2:存档很好;7z和python3.4-3.6都包含一个bug。在

考虑到这些工具的相对年龄,我想H1是正确的。在

变通办法

如果您不使用Windows并且信任存档的内容,那么使用常规shell命令可能会更简单。比如:

wget <the-long-url> -O /tmp/vertnet_latest_amphibians.zip
unzip /tmp/vertnet_latest_amphibians.zip vertnet_latest_amphibians.csv
rm -rf /tmp/vertnet_latest_amphibians.zip

或者您可以在Python中执行unzip

import os
os.system('unzip vertnet_latest_amphibians.zip vertnet_latest_amphibians.csv')

附带的

捕捉ImportError比检查 Python解释器:

try:
    from urllib.request import urlretrieve
except ImportError:
    from urllib import urlretrieve

相关问题 更多 >