从0到1手把手教你实现一个 Python 多线程下载器(二)

简介: 从0到1手把手教你实现一个 Python 多线程下载器(二)

带进度条的文件下载器

基础知识

获取文件大小 不难知道,要做一个进度条展示下载进度,我们得事先知道文件的大小以及每次写入文件的大小。还是以这个文件链接为例,展示如何获取待下载的文件大小

# 导入requests 库
import requests
# 文件下载直链
url = 'https://issuecdn.baidupcs.com/issue/netdisk/yunguanjia/BaiduNetdisk_7.2.8.9.exe'
# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE'
}
# 发起 head 请求,即只会获取响应头部信息
response = requests.head(url, headers=headers)
# 文件大小,以 B 为单位
file_size = response.headers.get('Content-Length')
if file_size is not None:
    file_size = int(file_size)
print('文件大小:', file_size, 'B')

代码运行输出

文件大小: 67765560 B


分块获取响应内容


上面的文件大小为:67765560 B。如果我们一次性下载 67765560 B 这么大的文件的话,进度条的跨度显然太大了,那么做这么一个进度条的意义并不大,所以我们需要考虑通过一个循环,分多次连续地读取响应直到读取完毕。

# 导入requests 库
import requests
# 文件下载直链
url = 'https://issuecdn.baidupcs.com/issue/netdisk/yunguanjia/BaiduNetdisk_7.2.8.9.exe'
# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE'
}
# 发起 head 请求,即只会获取响应头部信息
head = requests.head(url, headers=headers)
# 文件大小,以 B 为单位
file_size = head.headers.get('Content-Length')
if file_size is not None:
    file_size = int(file_size)
response = requests.get(url, headers=headers, stream=True)
# 一块文件的大小
chunk_size = 1024
# 记录已经读取的文件大小
read = 0
for chunk in response.iter_content(chunk_size=chunk_size):
    read += chunk_size
    read = min(read, file_size)
    print(f'已读取: {read} 总大小: {file_size}')


部分输出结果

已读取: 1024 总大小: 67765560
已读取: 2048 总大小: 67765560
已读取: 3072 总大小: 67765560
已读取: 4096 总大小: 67765560
已读取: 5120 总大小: 67765560
已读取: 6144 总大小: 67765560
已读取: 7168 总大小: 67765560
已读取: 8192 总大小: 67765560


通过以上操作,我们成功实现分段、连续下载文件。但是输出显然太多了,我们更希望有一个单行的进度条。 这里不得不说到 tqdm 这个进度条库

一个 tqdm 的使用例子

import time
from tqdm import tqdm
total = 100
for _ in tqdm(range(total)):
    time.sleep(0.1)

 

在终端或者jupyter运行上面的代码即可看到下面的动图如果想一次更新指定次数个进度怎么办呢?比如说进度总共是 100 ,每 10 个刷新一次进度

实现代码例子如下

mport time
from tqdm import tqdm
# 总进度
total = 100
# 每次刷新的进度
step = 10
# 总共要刷新的次数
flush_count = total//step
bar = tqdm(total=total)
for _ in range(flush_count):
    time.sleep(0.1)
    bar.update(step)
bar.close()i


以上代码可实现 每 10 个单位刷新一次直进度满 100

下面来给我们的下载器加进度条吧!

# 导入requests 库
import requests
# 导入 tqdm
from tqdm import tqdm
# 文件下载直链
url = 'https://issuecdn.baidupcs.com/issue/netdisk/yunguanjia/BaiduNetdisk_7.2.8.9.exe'
# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE'
}
file_name = 'BaiduNetdisk_7.2.8.9.exe'
# 发起 head 请求,即只会获取响应头部信息
head = requests.head(url, headers=headers)
# 文件大小,以 B 为单位
file_size = head.headers.get('Content-Length')
if file_size is not None:
    file_size = int(file_size)
response = requests.get(url, headers=headers, stream=True)
# 一块文件的大小
chunk_size = 1024
bar = tqdm(total=file_size, desc=f'下载文件 {file_name}')
with open(file_name, mode='wb') as f:
    # 写入分块文件
    for chunk in response.iter_content(chunk_size=chunk_size):
        f.write(chunk)
        bar.update(chunk_size)
# 关闭进度条
bar.close()


代码运行过程如下


就这样,我们成功实现了一个带进度条的文件下载器! 为了调用方便,我们可以考虑把它封装为函数,这里我直接附上代码了


相关文章
|
6天前
|
安全 数据处理 开发者
Python中的多线程编程:从入门到精通
本文将深入探讨Python中的多线程编程,包括其基本原理、应用场景、实现方法以及常见问题和解决方案。通过本文的学习,读者将对Python多线程编程有一个全面的认识,能够在实际项目中灵活运用。
|
1天前
|
Java Unix 调度
python多线程!
本文介绍了线程的基本概念、多线程技术、线程的创建与管理、线程间的通信与同步机制,以及线程池和队列模块的使用。文章详细讲解了如何使用 `_thread` 和 `threading` 模块创建和管理线程,介绍了线程锁 `Lock` 的作用和使用方法,解决了多线程环境下的数据共享问题。此外,还介绍了 `Timer` 定时器和 `ThreadPoolExecutor` 线程池的使用,最后通过一个具体的案例展示了如何使用多线程爬取电影票房数据。文章还对比了进程和线程的优缺点,并讨论了计算密集型和IO密集型任务的适用场景。
13 4
|
8天前
|
Python
Python中的多线程与多进程
本文将探讨Python中多线程和多进程的基本概念、使用场景以及实现方式。通过对比分析,我们将了解何时使用多线程或多进程更为合适,并提供一些实用的代码示例来帮助读者更好地理解这两种并发编程技术。
|
15天前
|
Java Python
python知识点100篇系列(16)-python中如何获取线程的返回值
【10月更文挑战第3天】本文介绍了两种在Python中实现多线程并获取返回值的方法。第一种是通过自定义线程类继承`Thread`类,重写`run`和`join`方法来实现;第二种则是利用`concurrent.futures`库,通过`ThreadPoolExecutor`管理线程池,简化了线程管理和结果获取的过程,推荐使用。示例代码展示了这两种方法的具体实现方式。
python知识点100篇系列(16)-python中如何获取线程的返回值
|
22天前
|
数据挖掘 程序员 调度
探索Python的并发编程:线程与进程的实战应用
【10月更文挑战第4天】 本文深入探讨了Python中实现并发编程的两种主要方式——线程和进程,通过对比分析它们的特点、适用场景以及在实际编程中的应用,为读者提供清晰的指导。同时,文章还介绍了一些高级并发模型如协程,并给出了性能优化的建议。
22 3
|
24天前
|
并行计算 安全 Java
Python 多线程并行执行详解
Python 多线程并行执行详解
46 3
|
17天前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
45 0
|
26天前
|
安全 Java 数据库连接
Python多线程编程:竞争问题的解析与应对策略
Python多线程编程:竞争问题的解析与应对策略
14 0
|
26天前
|
设计模式 监控 安全
Python多线程编程:特性、挑战与最佳实践
Python多线程编程:特性、挑战与最佳实践
33 0
|
26天前
|
安全 Java 数据库连接
Python多线程编程:竞争问题的解析与应对策略【2】
Python多线程编程:竞争问题的解析与应对策略【2】
12 0