Python3使用requests模块实现显示下载进度的方法详解
本文详解如何在Python3中利用requests模块实现文件下载进度的实时显示。通过设置stream参数启用流式传输,结合Response.iter_content分块读取数据,并自定义ProgressBar类利用\r控制光标刷新,从而在控制台输出美观的下载进度条。
本文介绍了一种在Python3环境下,利用requests模块实现文件下载进度显示的具体方法。内容包含配置要点与进度条类的完整实现,供读者参考学习。
一、配置request
1. 相关资料
请求的关键参数是stream=True。默认情况下,执行网络请求后响应体会立即全部下载。若希望推迟下载响应体,直到访问Response.content属性时才获取内容,可通过设置该参数来覆盖默认行为。
tarball_url = 'https://github.com/kennethreitz/requests/tarball/master' r = requests.get(tarball_url, stream=True)
此时仅下载响应头,连接保持打开状态,从而允许根据条件逐步获取内容。
if int(r.headers['content-length']) < TOO_LONG: content = r.content ...
可进一步使用Response.iter_content和Response.iter_lines方法来控制工作流,或者通过Response.raw从底层urllib3的urllib3.HTTPResponse获取更底层的控制。
from contextlib import closing
with closing(requests.get('http://httpbin.org/get', stream=True)) as r:
# Do things with the response here.
保持活动状态(持久连接)
得益于urllib3的支持,同一会话内的持久连接会自动处理。在同一会话中发出的任何请求,都会自动复用已建立的恰当连接。
注意:只有当响应体的所有数据被读取完毕后,连接才会被释放回连接池。因此,务必将stream设置为False,或者读取Response对象的content属性,以确保连接正确释放。
2. 下载文件并显示进度条
with closing(requests.get(self.url(), stream=True)) as response:
chunk_size = 1024 # 单次请求最大值
content_size = int(response.headers['content-length']) # 内容体总大小
progress = ProgressBar(self.file_name(), total=content_size,
unit="KB", chunk_size=chunk_size, run_status="正在下载", fin_status="下载完成")
with open(file_name, "wb") as file:
for data in response.iter_content(chunk_size=chunk_size):
file.write(data)
progress.refresh(count=len(data))
二、进度条类的实现
在Python3中,print()方法的默认结束符为end='\n'。调用完成后,光标自动切换到下一行,导致无法在原位置更新输出内容。
若将结束符改为“\r”,输出完成后光标会回到行首且不换行。此时再次调用print()方法,即可覆盖并更新这一行的输出内容。
结束符也可以使用“\d”,即退格符,使光标回退一格。可根据需要多次使用,按需求控制回退距离。
在结束这一行输出时,将结束符改回“\n”或不指定以使用默认值。
下面是一个格式化的进度条显示模块。代码如下:
class ProgressBar(object):
def __init__(self, title,
count=0.0,
run_status=None,
fin_status=None,
total=100.0,
unit='', sep='/',
chunk_size=1.0):
super(ProgressBar, self).__init__()
self.info = "【%s】%s %.2f %s %s %.2f %s"
self.title = title
self.total = total
self.count = count
self.chunk_size = chunk_size
self.status = run_status or ""
self.fin_status = fin_status or " " * len(self.status)
self.unit = unit
self.seq = sep
def __get_info(self):
# 【名称】状态 进度 单位 分割线 总数 单位
_info = self.info % (self.title, self.status,
self.count/self.chunk_size, self.unit, self.seq, self.total/self.chunk_size, self.unit)
return _info
def refresh(self, count=1, status=None):
self.count += count
# if status is not None:
self.status = status or self.status
end_str = "\r"
if self.count >= self.total:
end_str = '\n'
self.status = status or self.fin_status
print(self.__get_info(), end=end_str)
三、参考资料
http://cn.python-requests.org/en/latest/user/advanced.html
更多关于Python相关内容感兴趣的读者可查看本站专题:《Python函数使用技巧总结》、《Python面向对象程序设计入门与进阶教程》、《Python数据结构与算法教程》、《Python字符串操作技巧汇总》、《Python编码操作技巧总结》及《Python入门与进阶经典教程》
希望本文所述对大家Python程序设计有所帮助。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













