Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
testzip()在Python 2和Python 3上返回不同的结果_Python_Python 3.x_Python 2.x_Unzip_Zipfile - Fatal编程技术网

testzip()在Python 2和Python 3上返回不同的结果

testzip()在Python 2和Python 3上返回不同的结果,python,python-3.x,python-2.x,unzip,zipfile,Python,Python 3.x,Python 2.x,Unzip,Zipfile,使用zipfile模块解压缩Python中的大型数据文件在Python 2上正常工作,但在Python 3.6.0上会产生以下错误: BadZipFile:myfile.csv文件的错误CRC-32 我跟踪到错误处理代码检查CRC值 在Python2上使用ZipFile.testzip()不会返回任何结果(所有文件都可以)。在Python3上运行它会返回'myfile.csv',表明该文件存在问题 要在Python2和Python3上复制的代码(抱歉,需要300 MB的下载): 有人知道为什么会

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

BadZipFile:myfile.csv文件的错误CRC-32

我跟踪到错误处理代码检查CRC值

在Python2上使用
ZipFile.testzip()
不会返回任何结果(所有文件都可以)。在Python3上运行它会返回
'myfile.csv'
,表明该文件存在问题

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

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

archive.extract("vertnet_latest_amphibians.csv")

我无法从存档中提取Python 3。(在Mac OS X上)的一些调查结果可能会有所帮助

检查存档的运行状况 将文件设为只读,以防止意外更改:

$ 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
使用
zip
unzip
检查存档:

$ zip -T vertnet_latest_amphibians.zip
test of vertnet_latest_amphibians.zip OK

$ unzip -t vertnet_latest_amphibians.zip
Archive:  vertnet_latest_amphibians.zip
    testing: VertNet_Amphibia_eml.xml   OK
    testing: __MACOSX/                OK
    testing: __MACOSX/._VertNet_Amphibia_eml.xml   OK
    testing: vertnet_latest_amphibians.csv   OK
    testing: __MACOSX/._vertnet_latest_amphibians.csv   OK
No errors detected in compressed data of vertnet_latest_amphibians.zip
$ 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
正如@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
我的
zip
unzip
都很老了<代码>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)
摘录 使用
解压

$ zip -T vertnet_latest_amphibians.zip
test of vertnet_latest_amphibians.zip OK

$ unzip -t vertnet_latest_amphibians.zip
Archive:  vertnet_latest_amphibians.zip
    testing: VertNet_Amphibia_eml.xml   OK
    testing: __MACOSX/                OK
    testing: __MACOSX/._VertNet_Amphibia_eml.xml   OK
    testing: vertnet_latest_amphibians.csv   OK
    testing: __MACOSX/._vertnet_latest_amphibians.csv   OK
No errors detected in compressed data of vertnet_latest_amphibians.zip
$ 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
正如您所发现的,Python 3.6.0(也包括3.4.5和3.5.2)报告了错误的CRC

假设1:存档包含一个坏的CRC,它
zip
unzip
和 Python 2.7.13未能检测到<代码>7z
和Python 3.4-3.6都在做同样的工作 没错

假设2:档案是好的<代码>7z
和Python 3.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
附带的 捕捉
ImportError
比检查 Python解释器:

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

CRC值正常。zip中记录的“vertnet_latest_两栖动物.csv”的CRC为0x87203305。提取后,这确实是文件的CRC

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

您可以这样修复它(至少在Python 3.5.2中是这样):


作为@Kundor,将文件大小设置为最大值(2**32-1)将起作用,但对于任何大于4 GiB(4 GiB减去1字节)的文件都将失败,因此将其设置为ZIP64的最大大小(16 EiB减去1字节)

测试时间(927MB压缩和11GB文件提取)

网址:

文件:vertnet_latest_birds.csv


在我的例子中,问题是与提取时文件的实际大小相比(正如@nick matteo发现的),ZipInfo.file_size(Python 2.7)是错误的。我发现文件大小不匹配的原因是将unicode字符串传递给
zipfile.writestr()
函数。

在我的例子中,解决方案是在传递到
writest()函数之前将unicode编码为utf8:

zf = zipfile.ZipFile(...)
if isinstance(file_contents, unicode):
    file_contents = file_contents.encode("utf8")
zf.writestr("filename.txt", file_contents)
...

看起来我在示例中加入了一些本地州。很抱歉现在应该可以顺利运行了。嗯,如果可以的话,请添加用于运行此功能的Python的确切版本。它是
3.6.0
。我刚刚把它添加到问题中。我可以用
2.7.12
(正常)和
3.4.3
(失败)重新创建它。我现在必须离开这里,但我确实验证了ZipInfo中的CRC在两个Python版本中是相同的,所以我认为这是CRC32计算中的一个差异。顺便说一句,我的7-zip版本(自2010年以来我就没有更新过)也认为这个文件坏了。下载速度非常慢,在完成之前会中止。你能把文件镜像到别的地方吗?
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)
zf = zipfile.ZipFile(...)
if isinstance(file_contents, unicode):
    file_contents = file_contents.encode("utf8")
zf.writestr("filename.txt", file_contents)
...