进度条的显示

demo 01:

#!/usr/bin/python
#encoding:utf-8
import urllib
import os
def Schedule(a,b,c):
   '''
    a:已经下载的数据块
   b:数据块的大小
   c:远程文件的大小
   '''
   per = 100.0*a*b/c
   if per > 100:
      per = 100
   print '%.2f%%' % per
url = 'http://download.dinpay.com/member/DinpayPusreV2.1.15_08.apk'
#local = url.split('/')[-1]
local = os.path.join('f://APK/','DinpayPusreV2.1.15_08-1.apk')
urllib.urlretrieve(url,local,Schedule)
demo01
 

demo02:

我们对进度条的需求:一是进度信息在一行中显示;二是每次都能够动态擦除一行中上一次的内容。那么很自然的想到print有没有相应的转义符,还真有这么一个,”\r”。

import time
N = 1000
for i in range(N):
    print("进度:{0}%".format(round((i + 1) * 100 / N)), end="\r")
    time.sleep(0.01)
demo02

demo03:

环境:

  • Python 3.6
  • requests模块
  • 对应文件的下载链接 

讲解:

调用requests库函数时,默认verify=True,这会导致一个问题,当你的浏览器和网站SSL不匹配时,会报错。那解决办法也非常简单,就是把verify=False 这一句换成上一句。

既然要实现下载进度,那就要知道你要下载文件的总大小,还有你已经下载到的文件大小,那这些信心从哪得到呢?一般网页的Content-Length 就包含下载文件总大小,然后temp_size += len(chunk) 就是得到每次本地已经下载的文件大小,这样就能实现下载进度了(百分比)。

花哨的部分讲解,上面代码中调用标准输出刷新命令行,看到\r回车符了吧,相当于每次循环就回车到命令行首,把每一行重新刷新一遍,所以看起来是动态的下载。

有些人下载文件很大怎么办,内存都装不下怎么办?那就要指定chunk_size = 1024,具体大小可以自己设置, 意思是下载一点chunk 就写一点到磁盘。又有人问了,那我下载下载就断了,前面那些不是白下了。。。其实这个问题可以用断点续传解决,但是前提是,该网站的文件支持断点续传,查看demo04代码

代码:

import sys
import requests
import os

# 屏蔽warning信息,因为下面verify=False会报警告信息
requests.packages.urllib3.disable_warnings()


def download(url, file_path):
    # verify=False 这一句是为了有的网站证书问题,为True会报错
    r = requests.get(url, stream=True, verify=False)

    # 既然要实现下载进度,那就要知道你文件大小啊,下面这句就是得到总大小
    total_size = int(r.headers['Content-Length'])
    temp_size = 0

    with open(file_path, "w") as f:
        # iter_content()函数就是得到文件的内容,
        # 有些人下载文件很大怎么办,内存都装不下怎么办?
        # 那就要指定chunk_size=1024,大小自己设置,
        # 意思是下载一点写一点到磁盘。
        for chunk in r.iter_content(chunk_size=1024):
            if chunk:
                temp_size += len(chunk)
                f.write(chunk)
                f.flush()
                #############花哨的下载进度部分###############
                done = int(50 * temp_size / total_size)
                # 调用标准输出刷新命令行,看到\r回车符了吧
                # 相当于把每一行重新刷新一遍
                sys.stdout.write("\r[%s%s] %d%%" % ('' * done, ' ' * (50 - done), 100 * temp_size / total_size))
                sys.stdout.flush()
    print()  # 避免上面\r 回车符,执行完后需要换行了,不然都在一行显示


if __name__ == '__main__':

    link = r'https://api.gdc.cancer.gov/data/'
    UUID = r'2a4a3044-0b1a-4722-83ed-43ba5d6d25b0'
    # path是下载文件保存的路径
    path = r'F:\SYY\temp\a.txt'
    # url是文件网址链接
    url = os.path.join(link, UUID)
    # 调用上面下载函数即可
    download(url, path)
demo03

demo04:

import sys
import requests
import os

# 屏蔽warning信息
requests.packages.urllib3.disable_warnings()

def download(url, file_path):
    # 第一次请求是为了得到文件总大小
    r1 = requests.get(url, stream=True, verify=False)
    total_size = int(r1.headers['Content-Length'])

    # 这重要了,先看看本地文件下载了多少
    if os.path.exists(file_path):
        temp_size = os.path.getsize(file_path)  # 本地已经下载的文件大小
    else:
        temp_size = 0
    # 显示一下下载了多少   
    print(temp_size)
    print(total_size)
    # 核心部分,这个是请求下载时,从本地文件已经下载过的后面下载
    headers = {'Range': 'bytes=%d-' % temp_size}  
    # 重新请求网址,加入新的请求头的
    r = requests.get(url, stream=True, verify=False, headers=headers)

    # 下面写入文件也要注意,看到"ab"了吗?
    # "ab"表示追加形式写入文件
    with open(file_path, "ab") as f:
        for chunk in r.iter_content(chunk_size=1024):
            if chunk:
                temp_size += len(chunk)
                f.write(chunk)
                f.flush()

                ###这是下载实现进度显示####
                done = int(50 * temp_size / total_size)
                sys.stdout.write("\r[%s%s] %d%%" % ('' * done, ' ' * (50 - done), 100 * temp_size / total_size))
                sys.stdout.flush()
    print()  # 避免上面\r 回车符


if __name__ == '__main__':
    link = r'https://api.gdc.cancer.gov/data/'
    UUID = r'2a4a3044-0b1a-4722-83ed-43ba5d6d25b0'
    path = r'F:\SYY\temp\a.txt'
    url = os.path.join(link, UUID)
    # 调用一下函数试试
    download(url, path)
demo04

另外有

progressbar库:下载地址:https://pypi.python.org/pypi/progressbar2

简单用法1:

import time
import progressbar
p = progressbar.ProgressBar()
N = 1000
for i in p(range(N)):
    time.sleep(0.01)

简单用法2:

import time
import progressbar
p = progressbar.ProgressBar()
N = 1000
p.start(N)
for i in range(N):
    time.sleep(0.01)
    p.update(i+1)
p.finish()
  • 高级点的用法(自己配置输出格式):
import time
import progressbar
bar = progressbar.ProgressBar(widgets=[
    ' [', progressbar.Timer(), '] ',
    progressbar.Percentage(),
    ' (', progressbar.ETA(), ') ',
])
for i in bar(range(1000)):
    time.sleep(0.01)

输出格式:
[Elapsed Time: 0:00:10] 100% (Time: 0:00:10)

主要方式有如下几种,可自由搭配:

'Timer', # 计时器
'ETA', # 预计剩余时间
'AbsoluteETA', # 预计结束的绝对时间,耗时很长时使用较方便
'Percentage', # 百分比进度,30%
'SimpleProgress', # 计数进度,300/1000
'Counter', # 单纯计数
'Bar' # “#”号进度条

如:

import time
import progressbar
bar = progressbar.ProgressBar(widgets=[
    progressbar.Percentage(),
    ' (', progressbar.SimpleProgress(), ') ',
    ' (', progressbar.AbsoluteETA(), ') ',])
for i in bar(range(1000)):
    time.sleep(0.01)

参考:https://blog.csdn.net/saltriver/article/details/53055942



猜你喜欢

转载自www.cnblogs.com/mxhmxh/p/10278601.html