从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 秒左右。


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


相关文章
|
9天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
19天前
|
算法 数据处理 Python
Python并发编程:解密异步IO与多线程
本文将深入探讨Python中的并发编程技术,重点介绍异步IO和多线程两种常见的并发模型。通过对比它们的特点、适用场景和实现方式,帮助读者更好地理解并发编程的核心概念,并掌握在不同场景下选择合适的并发模型的方法。
|
1月前
|
并行计算 安全 Unix
Python教程第8章 | 线程与进程
本章主要讲解了线程与进程的概念,多线程的运用以及Python进程的相关案例学习
36 0
|
1月前
|
安全 Java 关系型数据库
深入探究Python的多线程与异步编程:实战与最佳实践
【2月更文挑战第1天】 深入探究Python的多线程与异步编程:实战与最佳实践
112 0
|
1月前
|
分布式计算 并行计算 Java
浅析Python自带的线程池和进程池
浅析Python自带的线程池和进程池
79 0
|
27天前
|
安全 Python
Python中的并发编程:多线程与多进程技术探究
本文将深入探讨Python中的并发编程技术,重点介绍多线程和多进程两种并发处理方式的原理、应用场景及优缺点,并结合实例分析如何在Python中实现并发编程,以提高程序的性能和效率。
|
1月前
|
数据采集 存储 Java
「多线程大杀器」Python并发编程利器:ThreadPoolExecutor,让你一次性轻松开启多个线程,秒杀大量任务!
「多线程大杀器」Python并发编程利器:ThreadPoolExecutor,让你一次性轻松开启多个线程,秒杀大量任务!
|
1月前
|
安全 调度 Python
Python中如何实现多线程?请举例说明。
Python中如何实现多线程?请举例说明。
14 0
|
3天前
|
调度 Python
Python多线程、多进程与协程面试题解析
【4月更文挑战第14天】Python并发编程涉及多线程、多进程和协程。面试中,对这些概念的理解和应用是评估候选人的重要标准。本文介绍了它们的基础知识、常见问题和应对策略。多线程在同一进程中并发执行,多进程通过进程间通信实现并发,协程则使用`asyncio`进行轻量级线程控制。面试常遇到的问题包括并发并行混淆、GIL影响多线程性能、进程间通信不当和协程异步IO理解不清。要掌握并发模型,需明确其适用场景,理解GIL、进程间通信和协程调度机制。
18 0
|
18天前
|
数据采集 Java API
python并发编程: Python使用线程池在Web服务中实现加速
python并发编程: Python使用线程池在Web服务中实现加速
17 3
python并发编程: Python使用线程池在Web服务中实现加速