使用Python 3和requests实现进度条功能

4

我正尝试使用Python的requests库下载文件。在Python 2.7中可以工作,但现在不行了。我非常困惑,一定有更简单的答案。由于文件可能相当大,我真的希望能有一个进度条,因此我正在使用Python进度条来完成这项工作。

                r = requests.get(file_url, data={'track': 'requests'})
                size = int(r.headers['Content-Length'].strip())
                self.bytes = 0
                widgets = [name, ": ", Bar(marker="|", left="[", right=" "),
                    Percentage(), " ",  FileTransferSpeed(), "] ",
                    self,
                    " of {0}MB".format(round(size / 1024 / 1024, 2))]
                pbar = ProgressBar(widgets=widgets, maxval=size)
                pbar.start()

                file = b""
                for chunk in r.iter_content()
                    if chunk:
                        file += chunk

                        self.bytes += 1
                        pbar.update(self.bytes)

我发现使用iter_content是获取连续更新的最佳方法。我尝试使用iter_lines,但它会弄乱文件。下载会突然停止且非常慢,即使下载了10%,也需要15分钟才能完成。同时,在字节模式下打开文件并写入内容是行不通的,它根本不会抛出错误。而当我尝试使用以下代码打印块所包含的内容时:

print(chunk.decode("utf-8")

工作正常,但只有少数字符。在某个时候它会抱怨

UnicodeDecodeError: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte

即使在iter_content中使用“decode_unicode=True”,也没有任何作用。我感到困惑,不知道该怎么办。使用Py3k不应该这么难。

1个回答

4

已经成功解决了。这是更新后的代码:

r = requests.get(file_url)
size = int(r.headers['Content-Length'].strip())
self.bytes = 0
widgets = [name, ": ", Bar(marker="|", left="[", right=" "),
    Percentage(), " ",  FileTransferSpeed(), "] ",
    self,
    " of {0}MB".format(str(round(size / 1024 / 1024, 2))[:4])]
pbar = ProgressBar(widgets=widgets, maxval=size).start()
file = []
for buf in r.iter_content(1024):
    if buf:
        file.append(buf)
        self.bytes += len(buf)
        pbar.update(self.bytes)
pbar.finish()

下载速度已从7kb/s提升至400+ kb/s,并且完美运行。

这实际上会成为一个进度条,表示将数据写入文件的进度,因为请求在执行requests.get()调用时已完成。 - antihero
requests.get()函数返回一个Response对象。除非你对它进行操作(例如r = requests.get(file_url); r.text),否则它实际上不会做任何事情。我在下载内容时迭代了它。之后我实际上还得将其保存到文件中 :) - thabubble
@thabubble 实际上,你需要调用 requests.get(file_url, prefetch=False) 才能证明你的说法是正确的。否则,@antihero 是完全正确的。 - heycosmo
好吧,那我不知道为什么它能工作。但是它确实可以。据我所见,我所做的是“r = self.s.get(file_url, data={'track': 'requests'})”,然后使用“for char in r.iter_content():”进行迭代,它绝对有效。你可以看到它下载了。但这是很久以前的事情了,我可能有错的文件。但是在我发布答案之后,它被编辑过。我记得它只会下载头部而不是正文。要下载正文,您需要使用r.text或r.iter_content()。 - thabubble

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接