Python中的终端进度条

378 阅读5分钟

在靠近用户的地方部署容器

本工程教育(EngEd)计划由科支持。

在全球范围内即时部署容器。Section是经济实惠、简单而强大的。

免费开始吧。

Python中的终端进度条

11月2日, 2021

也许你的应用程序涉及到通过终端/控制台在某些时候进行的文件上传或下载。在某个时候,你会想在上述界面中显示进度。终端进度条是一种很好的方式,可以让用户直观地看到一个基本任务的进展。我们将看看如何使用文件下载来做到这一点。

在Python中有各种库可以做到这一点,包括tqdm、Progress、Alive Progress等。

先决条件

要继续学习本教程,你需要具备以下条件。

  • 对Python有良好的理解。

在Python中会有一些很深的概念,所以需要有很好的理解。

因为我们要做的是与终端相连,所以我们不会使用任何基于笔记本的技术。

关于Python中文件下载的入门知识

在进入主题之前,我们首先看一下Python中的基本下载脚本。然后,我们将下载一个图像。

import urllib.request

def Handle_Progress(block_num, block_size, total_size):
        read_data= 0
        # calculating the progress
        # storing a temporary value  to store downloaded bytesso that we can add it later to the overall downloaded data
        temp = block_num * block_size
        read_data = temp + read_data
        #calculating the remaining size
        remaining_size = total_size - read_data
        if(remaining_size<=0):
            downloaded_percentage = 100
            remaining_size = 0
        else:
            downloaded_percentage = int(((total_size-remaining_size) / total_size)*(100))
              
        print(read_data," : ", remaining_size," : ", downloaded_percentage," : ", total_size)
            
def Download_File():
        #the url where the file is found
        download_url = 'https://sacco.terrence-aluda.com/sacco/images/ab1.jpg'
        #opening the file
        site = urllib.request.urlopen(download_url)
        #getting the meta data
        meta = site.info()
        print("File size in bytes", meta.get("Content-Length"))
        print("Downloaded data: Remaining size: Downloaded percentage: Total size")
        #where the file will be saved
        save_location = 'thispic.png'
        #downloading the file
        urllib.request.urlretrieve(download_url,save_location, Handle_Progress)
        
Download_File()

Download_File() 函数首先从文件的元响应头信息Content-Length获得文件的字节大小。在得到文件的内容后,这是用导入模块的urlopen() 方法完成的。

之后,它开始使用urlretrieve() 方法下载文件。这个方法需要三个参数,解释如下。

  1. download_url - 要下载的文件所在的URL。
  2. save_location - 下载的文件将被存储的位置。
  3. Handle_Progress - 处理下载进度的函数作为一个回调传递。我们将在下一部分看一下这个函数。

在Python或其他语言中,回调是在执行完某段代码后执行的函数。它们通常作为其他函数的参数传入。例如,一个日常用例是在一个文件从机器的存储空间加载/读取完毕后显示一些文本。在这里阅读更多关于Python的回调。

def Handle_Progress(block_num, block_size, total_size):
        read_data= 0
        # calculating the progress
        # storing a temporary value  to store downloaded bytes so that we can add it later to the overall downloaded data
        temp = block_num * block_size
        read_data = temp + read_data
        #calculating the remaining size
        remaining_size = total_size - read_data
        if(remaining_size<=0):
            downloaded_percentage = 100
            remaining_size = 0
        else:
            downloaded_percentage = int(((total_size-remaining_size) / total_size)*(100))
              
        print(read_data," : ", remaining_size," : ", downloaded_percentage," : ", total_size)

这个函数需要三个参数。

  1. block_num - 块的编号。该方法以块为单位获取文件。
  2. block_size - 以字节为单位的块的大小。
  3. total_size - 文件的总大小,以字节为单位。

使用这三个参数,它计算出下载的大小(read_data),剩余的大小(remaining_size),以及下载的百分比(downloaded_percentage)。

它通过计算区块编号乘以区块大小来获得下载的大小,然后反复添加,直到文件下载完毕。

if 函数检查剩余大小。如果它小于0,那么就意味着文件已经完全下载完毕。因此,下载的百分比是100%,而剩余的大小是0。

在运行该文件时,你应该看到这个输出。当然,它不是那么漂亮,但它只是给你一个进度的概念。

File size in bytes 10905
Downloaded data: Remaining size: Downloaded percentage: Total size
0  :  10905  :  0  :  10905
8192  :  2713  :  75  :  10905
16384  :  0  :  100  :  10905

它输出了几次,因为urllib.request.urlretrieve() 方法在文件完成之前运行了几次。

进度条

正如我们所看到的,我们产生的进度看起来并不那么直观。由于这个原因,我们不得不寻求进度条的帮助。好消息是,在Python中,我们有几个库可以用来执行这个任务。在我们的案例中,我们不会使用任何一个库,但我们将建立我们的简单条。我们将使用requests 库来完成,因为它可以轻松地迭代HTTP响应。

这段代码比较简单,没有像前面那样使用函数,但概念仍然是一样的。因此,你可以在以后修改它以适应你的情况。

让我们来看看这个脚本。

import requests

link = "https://sacco.terrence-aluda.com/sacco/images/"
file_name = "ab1.jpg"
#creating the file with write binary flag
with open(file_name, "wb") as f:
    print("Downloading %s" % file_name)
    response = requests.get(link)
    #getting the file size
    total_size = response.headers.get('content-length')
    if total_size is None: # no content length header
        f.write(response.content)
    else:
        downloaded_data = 0
        total_size = int(total_size)
        for file_data in response.iter_content(chunk_size=8192):
            #storing the downloaded data
            downloaded_data += len(file_data)
            #writing the contents to the file
            f.write(file_data)
            #calculating what number of characters is to be displayed in the bar
            portion = int(50 * downloaded_data / total_size)
            print("[%s]" % ('#' * portion) )

**注意:**一定要用pip安装requests 库。

$ pip install requests

这是一个with 语句,它用指定的名称打开一个文件,并以二进制方式写入。然后它在终端打印一个*"下载file_name "*的语句。

然后我们像以前一样,得到文件的大小。之后,我们检查是否存在 "content-length "头。如果没有,我们就把HTTP响应的内容写到打开的文件中。

for 循环中,我们以8192的块大小遍历HTTP响应,尽管块大小并不重要。除了0或负数之外,你可以在这里放置任何数字。

这个逻辑和前面的代码片段比较相似,但是我们写了一个语句来计算要显示的字符数。我们想显示50个#符号,每个符号代表下载文件的2%。如果我们想要10个符号,我们可以在那里写10个,每个代表10%,以此类推。

portion = int(50 * downloaded_data / total_size)

代表的百分比=#号总数*(下载的数据/总文件大小)

在打印语句中,我们将#号与我们在刚才讨论的语句中设定的数字相乘,即50倍。

我们将看到这样一个输出。

Downloading ab1.jpg
[##################################################]

进一步阅读

你可以通过这些链接,看看用几行代码和更多的动画功能快速完成相同任务的库。

  1. 进展
  2. tqdm
  3. 活着的Progress

Progress是一个很好的探索对象。下面是一个用计时功能制作的例子。

import time
from progress.bar import FillingSquaresBar

bar = FillingSquaresBar('Downloading')
for item in range(100):
    bar.next()
    time.sleep(1)
bar.finish()

我们在增量(time.sleep(1))之前让条形图延迟一秒。

它将显示这个。

Downloading ▣▣▣▣▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢ 15%

它有很多不同类型的条可以选择。在它的文档中可以找到它们。

这里有一篇文章演示了它们的用法。

总结

我们看了Python中下载文件的基本过程以及如何显示下载的进度。我希望你能进一步深入研究。


同行评议贡献者:。Lalithnarayan C

类似文章

[

How to Create a Reusable React Form component Hero Image

语言

如何创建一个可重复使用的React表单组件

阅读更多

](www.section.io/engineering…

Building a payroll system with next.js Hero Image

语言, Node.js

用Next.js构建一个薪资系统

阅读更多

](www.section.io/engineering…

Creating and Utilizing Decorators in Django example image

架构

在Django中创建和使用装饰器

阅读更多

](www.section.io/engineering…)