用python下载大zip文件

Posted

技术标签:

【中文标题】用python下载大zip文件【英文标题】:Download big zip file with python 【发布时间】:2012-04-24 20:07:11 【问题描述】:

我有多个返回 zip 文件的 URL。大多数文件,我可以使用 urllib2 库下载如下:

request = urllib2.urlopen(url)
zip_file = request.read()

我遇到的问题是其中一个文件的大小为 35Mb(压缩),我永远无法使用此库完成下载。我可以正常使用wget和浏览器下载它。

我曾尝试像这样以块的形式下载文件:

request = urllib2.urlopen(url)
buffers = []
while True:
    buffer = request.read(8192)
    if buffer:
        buffers.append(buffer)
    else:
        break
final_file = ''.join(buffers)

但这也没有完成下载。没有引发错误,因此很难调试正在发生的事情。不幸的是,我无法在此处发布 url / 文件的示例。

有什么建议/意见吗?

【问题讨论】:

如果没有更多信息或重现它的 URL,很难调试。但是,为什么不直接使用final_file = request.read()?您上面的代码正在构建一个字符串数组,它将所有数据存储在内存中,因此我认为没有任何理由使代码复杂化以一次读取块。 How do I download a zip file in python using urllib2? 的可能重复项 @benhoyt 这是我的第一次尝试,但没有成功。这就是为什么我试图将文件分成块 Stream large binary files with urllib2 to file的可能重复 与 Masi 建议的不同,但可能与 @ChristopheD 相同。至少,问题和建议的解决方案似乎非常接近 【参考方案1】:

这是从我的应用程序中复制/粘贴的,它会下载它自己的更新安装程序。它以块为单位读取文件并立即将块保存在磁盘上的输出文件中。

def DownloadThreadFunc(self):
    try:
        url = self.lines[1]
        data = None
        req = urllib2.Request(url, data, )
        handle = urllib2.urlopen(req)

        self.size = int(handle.info()["Content-Length"])
        self.actualSize = 0
        name = path.join(DIR_UPDATES, url.split("/")[-1])
        blocksize = 64*1024

        fo = open(name, "wb")
        while not self.terminate:
            block = handle.read(blocksize)
            self.actualSize += len(block)
            if len(block) == 0:
                break
            fo.write(block)
        fo.close()
    except (urllib2.URLError, socket.timeout), e:
        try:
            fo.close()
        except:
            pass
        error("Download failed.", unicode(e))  

如果需要,我使用self.sizeself.actualSize 在 GUI 线程中显示下载进度,并使用self.terminate 从 GUI 按钮取消下载。

【讨论】:

这很完美!非常感谢。但是你能告诉我为什么我的简化版不起作用吗? 不知道。但我有点怀疑这种结构:if buffer:。我喜欢将块直接存储到磁盘,这样在输出文件中也可以看到进度。 我明白你的意思。我尝试了您的代码版本,也将文件仅存储在内存中,并且效果也很好。会不会是我的初始缓冲区大小(太小)? 我认为可能是这种情况。你的代码什么时候卡住了?文件是否已经下载到内存中?添加一些关于您已经下载了多少、数据大小等的调试打印输出。 我没有使用“如果不阻止”,它工作正常。似乎是块大小太小了。这是唯一的区别。还是谢谢!

以上是关于用python下载大zip文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 python ftplib 下载二进制格式的 zip 文件

CentOS 安装 opencv, 解决 Python cv2 module 问题(终极解决方法)

CentOS 安装 opencv, 解决 Python cv2 module 问题(终极解决方法)

使用 Python 下载 zip 文件给出 HTTP 403

Python3 用 requests 2.x 下载大文件

下载一个 zip 文件并使用 Python3 将其提取到内存中