本文实例讲述了Python3使用requests模块实现显示下载进度的方法。分享给大家供大家参考,具体如下:
一、配置request
1. 相关资料
请求关键参数:stream=True
。默认情况下,当你进行网络请求后,响应体会立即被下载。你可以通过 stream 参数覆盖这个行为,推迟下载响应体直到访问 Response.content
属性。
1
2
|
tarball_url = 'https://github.com/kennethreitz/requests/tarball/master'
r = requests.get(tarball_url, stream = True )
|
此时仅有响应头被下载下来了,连接保持打开状态,因此允许我们根据条件获取内容:
1
2
3
|
if int (r.headers[ 'content-length' ]) < TOO_LONG:
content = r.content
...
|
进一步使用 Response.iter_content
和 Response.iter_lines
方法来控制工作流,或者以 Response.raw
从底层urllib3的 urllib3.HTTPResponse
1
2
3
|
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. 下载文件并显示进度条
1
2
3
4
5
6
7
8
9
|
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=' '),当调用完之后,光标自动切换到下一行,此时就不能更新原有输出。
将结束符改为“ ”,输出完成之后,光标会回到行首,并不换行。此时再次调用print()方法,就会更新这一行输出了。
结束符也可以使用“d”,为退格符,光标回退一格,可以使用多个,按需求回退。
在结束这一行输出时,将结束符改回“ ”或者不指定使用默认
下面是一个格式化的进度条显示模块。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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 = " "
if self .count > = self .total:
end_str = ' '
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程序设计有所帮助。
原文链接:https://blog.csdn.net/supercooly/article/details/51046561