怎么用Python展示文件下载进度条

发布时间:2021-11-03 17:17:03 作者:iii
来源:亿速云 阅读:350
# 怎么用Python展示文件下载进度条

在文件下载过程中显示进度条不仅能提升用户体验,还能帮助开发者监控传输状态。本文将详细介绍5种用Python实现下载进度条的方法,涵盖标准库和第三方模块的解决方案。

## 为什么需要下载进度条?

1. **用户感知**:让用户明确知道下载进度和剩余时间
2. **调试辅助**:开发者可以直观看到传输速率和异常
3. **交互体验**:比静态文字更友好的信息展示方式

## 基础方法:使用urllib.request

Python标准库提供了最基本的下载进度实现方案:

```python
import urllib.request
import os

def download_with_progress(url, filename):
    def reporthook(blocknum, blocksize, totalsize):
        downloaded = blocknum * blocksize
        percent = downloaded * 100 / totalsize
        print(f"\r下载进度: {percent:.2f}% ({downloaded}/{totalsize} bytes)", end="")
    
    urllib.request.urlretrieve(url, filename, reporthook)
    print("\n下载完成!")

# 使用示例
url = "https://example.com/largefile.zip"
filename = "largefile.zip"
download_with_progress(url, filename)

优缺点分析

进阶方案:tqdm库

tqdm是Python生态中最流行的进度条库:

import requests
from tqdm import tqdm

def download_with_tqdm(url, filename):
    response = requests.get(url, stream=True)
    total_size = int(response.headers.get('content-length', 0))
    
    with open(filename, 'wb') as file, tqdm(
        desc=filename,
        total=total_size,
        unit='iB',
        unit_scale=True,
        unit_divisor=1024,
    ) as bar:
        for data in response.iter_content(chunk_size=1024):
            size = file.write(data)
            bar.update(size)

# 使用示例
url = "https://example.com/largefile.zip"
filename = "largefile.zip"
download_with_tqdm(url, filename)

功能特点

专业方案:progressbar2库

progressbar2提供了更专业的进度条组件:

import requests
import progressbar

def download_with_progressbar2(url, filename):
    response = requests.get(url, stream=True)
    total_size = int(response.headers.get('content-length', 0))
    
    widgets = [
        progressbar.Percentage(),
        ' ', progressbar.Bar(),
        ' ', progressbar.ETA(),
        ' ', progressbar.FileTransferSpeed(),
    ]
    
    with open(filename, 'wb') as file:
        with progressbar.ProgressBar(max_value=total_size, widgets=widgets) as bar:
            for chunk in response.iter_content(chunk_size=1024):
                file.write(chunk)
                bar.update(len(chunk))

# 使用示例
url = "https://example.com/largefile.zip"
filename = "largefile.zip"
download_with_progressbar2(url, filename)

高级功能

异步方案:aiohttp + asyncio

对于异步下载场景,可以使用以下方案:

import aiohttp
import asyncio
from tqdm.asyncio import tqdm_asyncio

async def async_download(url, filename):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            total_size = int(response.headers.get('content-length', 0))
            
            with open(filename, 'wb') as file:
                with tqdm_asyncio(
                    total=total_size,
                    unit='B',
                    unit_scale=True,
                    desc=filename
                ) as bar:
                    async for chunk in response.content.iter_chunked(1024):
                        file.write(chunk)
                        bar.update(len(chunk))

# 使用示例
async def main():
    url = "https://example.com/largefile.zip"
    filename = "largefile.zip"
    await async_download(url, filename)

asyncio.run(main())

异步优势

终端美化方案:rich库

rich库可以创建美观的控制台输出:

import requests
from rich.progress import (
    Progress,
    DownloadColumn,
    TransferSpeedColumn,
    TimeRemainingColumn,
)

def download_with_rich(url, filename):
    response = requests.get(url, stream=True)
    total_size = int(response.headers.get('content-length', 0))
    
    with Progress(
        "[progress.description]{task.description}",
        DownloadColumn(),
        "[progress.percentage]{task.percentage:>3.0f}%",
        TransferSpeedColumn(),
        TimeRemainingColumn(),
    ) as progress:
        task = progress.add_task("下载", total=total_size)
        
        with open(filename, 'wb') as file:
            for chunk in response.iter_content(chunk_size=1024):
                file.write(chunk)
                progress.update(task, advance=len(chunk))

# 使用示例
url = "https://example.com/largefile.zip"
filename = "largefile.zip"
download_with_rich(url, filename)

rich特性

性能优化技巧

  1. 分块大小调整:根据网络状况调整chunk_size

    • 局域网:较大的chunk_size(如8KB)
    • 移动网络:较小的chunk_size(如1KB)
  2. 断点续传实现

def resume_download(url, filename):
    file_size = os.path.getsize(filename) if os.path.exists(filename) else 0
    headers = {'Range': f'bytes={file_size}-'}
    
    with requests.get(url, headers=headers, stream=True) as response:
        total_size = file_size + int(response.headers.get('content-length', 0))
        
        with open(filename, 'ab') as file, tqdm(
            initial=file_size,
            total=total_size,
            unit='iB',
            unit_scale=True,
        ) as bar:
            for chunk in response.iter_content(chunk_size=1024):
                file.write(chunk)
                bar.update(len(chunk))
  1. 错误重试机制
from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def reliable_download(url, filename):
    # 下载实现代码

总结对比表

方法 易用性 功能丰富度 性能 适用场景
urllib ★★★☆☆ ★★☆☆☆ ★★★☆☆ 简单脚本
tqdm ★★★★★ ★★★★☆ ★★★★☆ 日常使用
progressbar2 ★★★★☆ ★★★★★ ★★★☆☆ 专业需求
aiohttp ★★★☆☆ ★★★☆☆ ★★★★★ 高并发
rich ★★★★☆ ★★★★☆ ★★★☆☆ 终端美化

结语

根据实际需求选择合适的进度条实现方案: - 快速原型开发:使用tqdm - 生产环境:考虑progressbar2或rich - 高性能需求:采用异步方案 - 零依赖场景:标准库解决方案

完整的示例代码已托管在GitHub仓库。 “`

这篇文章包含了约1900字,采用Markdown格式编写,涵盖了从基础到高级的多种Python下载进度条实现方案,并提供了性能优化建议和方案对比。

推荐阅读:
  1. python 知识星球文件下载
  2. 用代码解析Python如何实现进度条和时间预估

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python

上一篇:Kubernetes1.4版本的新功能是什么

下一篇:banana pi BPI-M64 四核64位开源单板计算机的实例分析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》