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

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

实例代码

函数形式的带进度条的单线程文件下载器

# 导入requests 库
import requests
# 导入 tqdm
from tqdm import tqdm
def download(url: str, file_name: str):
    '''
    根据文件直链和文件名下载文件
    Parameters
    ----------
    url: 文件直链
    file_name : 文件名(文件路径)
    '''
    # 文件下载直链
    # 请求头
    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
    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()
if "__main__" == __name__:
    url = 'https://issuecdn.baidupcs.com/issue/netdisk/yunguanjia/BaiduNetdisk_7.2.8.9.exe'
    file_name = 'BaiduNetdisk_7.2.8.9.exe'
    download(url, file_name)


多线程文件下载器

絮絮叨叨


早些年还没会编程的时候,我喜欢寻找各种高速的下载工具,比如说简单易用的 IDM 以及命令行多线程下载工具 Aria2。它们的下载速度确实让人惊艳。通过查询一些资料,我大概了解到它们下载速度快的原因之一是它们对同一个服务器建立多个连接,然后分块请求响应的内容,于是人多力量大,下载速度自然就提高了。


基础知识

假设我们有下面这么一段代码


单线程程序

import time
def say(number: int):
    print(number)
    time.sleep(0.5)
for i in range(5):
    say(i)


代码运行输出

0
1
2
3
4


不难发现,该代码实现的功能是每间隔 0.5 秒输出一次数字,一共重复 5 次。所以这段程序耗时在 2.5 秒左右。 如果我们使用多线程呢?譬如对于每一次操作均开启一个线程,结果会是怎么样?

为了简化多线程的写法,我查阅了相关资料,发现了一个很好用的多线程库

multitasking

如果你没有安装它,则可以使用 pip 工具,在终端运行下面的代码进行安装(前提是 pip 安装目录在环电脑境变量里面)


pip install multitasking

使用它之后,我们只需要给自定义的函数前面加上一行代码(装饰器)即可在调用函数时,为被调用的这个函数开启新的线程。下面是一个使用例子


以上代码的多线程版本如下

import time
# 导入用于多线程操作的库
# 这样子仅需要在自定义的函数前面使用装饰器即可将函数开启新的线程
import multitasking
import signal
# 按快捷键 ctrl + c 终止已开启的全部线程
signal.signal(signal.SIGINT, multitasking.killall)
# 多线程装饰器
@multitasking.task
def say(number: int):
    print(number)
    time.sleep(0.5)
start_time = time.time()
for i in range(5):
    say(i)
# 等待全部线程执行完毕
multitasking.wait_for_tasks()
end_time = time.time()
print('耗时:', end_time-start_time, '秒')


代码运行输出

0
1
2
3
4
耗时: 0.5063784122467041 秒


同样是每 0.5 秒输出一个数字,上面的代码因为使用多线程,耗时只有 0.5 秒左右,而之前的单线程版本耗时是 2.5 秒左右。


这里面用了一个装饰器,要展开的话稍微有些麻烦,感兴趣的先自己去了解或者与我交流吧。在这篇文章中,我们只需要掌握怎么简单地使用它来完成一个多线程操作即可。


相关文章
|
2月前
|
安全 数据处理 开发者
Python中的多线程编程:从入门到精通
本文将深入探讨Python中的多线程编程,包括其基本原理、应用场景、实现方法以及常见问题和解决方案。通过本文的学习,读者将对Python多线程编程有一个全面的认识,能够在实际项目中灵活运用。
|
26天前
|
并行计算 数据处理 调度
Python中的并发编程:探索多线程与多进程的奥秘####
本文深入探讨了Python中并发编程的两种主要方式——多线程与多进程,通过对比分析它们的工作原理、适用场景及性能差异,揭示了在不同应用需求下如何合理选择并发模型。文章首先简述了并发编程的基本概念,随后详细阐述了Python中多线程与多进程的实现机制,包括GIL(全局解释器锁)对多线程的影响以及多进程的独立内存空间特性。最后,通过实例演示了如何在Python项目中有效利用多线程和多进程提升程序性能。 ####
|
1月前
|
Java Unix 调度
python多线程!
本文介绍了线程的基本概念、多线程技术、线程的创建与管理、线程间的通信与同步机制,以及线程池和队列模块的使用。文章详细讲解了如何使用 `_thread` 和 `threading` 模块创建和管理线程,介绍了线程锁 `Lock` 的作用和使用方法,解决了多线程环境下的数据共享问题。此外,还介绍了 `Timer` 定时器和 `ThreadPoolExecutor` 线程池的使用,最后通过一个具体的案例展示了如何使用多线程爬取电影票房数据。文章还对比了进程和线程的优缺点,并讨论了计算密集型和IO密集型任务的适用场景。
60 4
|
20天前
|
数据采集 Java Python
爬取小说资源的Python实践:从单线程到多线程的效率飞跃
本文介绍了一种使用Python从笔趣阁网站爬取小说内容的方法,并通过引入多线程技术大幅提高了下载效率。文章首先概述了环境准备,包括所需安装的库,然后详细描述了爬虫程序的设计与实现过程,包括发送HTTP请求、解析HTML文档、提取章节链接及多线程下载等步骤。最后,强调了性能优化的重要性,并提醒读者遵守相关法律法规。
54 0
|
2月前
|
Python
Python中的多线程与多进程
本文将探讨Python中多线程和多进程的基本概念、使用场景以及实现方式。通过对比分析,我们将了解何时使用多线程或多进程更为合适,并提供一些实用的代码示例来帮助读者更好地理解这两种并发编程技术。
|
2月前
|
Java Python
python知识点100篇系列(16)-python中如何获取线程的返回值
【10月更文挑战第3天】本文介绍了两种在Python中实现多线程并获取返回值的方法。第一种是通过自定义线程类继承`Thread`类,重写`run`和`join`方法来实现;第二种则是利用`concurrent.futures`库,通过`ThreadPoolExecutor`管理线程池,简化了线程管理和结果获取的过程,推荐使用。示例代码展示了这两种方法的具体实现方式。
python知识点100篇系列(16)-python中如何获取线程的返回值
|
2月前
|
数据挖掘 程序员 调度
探索Python的并发编程:线程与进程的实战应用
【10月更文挑战第4天】 本文深入探讨了Python中实现并发编程的两种主要方式——线程和进程,通过对比分析它们的特点、适用场景以及在实际编程中的应用,为读者提供清晰的指导。同时,文章还介绍了一些高级并发模型如协程,并给出了性能优化的建议。
35 3
|
2月前
|
并行计算 安全 Java
Python 多线程并行执行详解
Python 多线程并行执行详解
74 3
|
2月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
70 0
|
2月前
|
安全 Java 数据库连接
Python多线程编程:竞争问题的解析与应对策略
Python多线程编程:竞争问题的解析与应对策略
29 0