在 Python 开发中,我们经常需要处理大量的计算任务或 I/O 操作,比如:
- 批量爬取网页数据
- 处理大量文件
- 批量下载资源
- 进行复杂的数学计算
如果我们按照顺序执行这些任务,效率可能会很低。而 Python 提供了 threading
(多线程)和 multiprocessing
(多进程)模块,可以帮助我们并行执行任务,提高程序的运行效率。
本篇博客将介绍: ✅ 多线程(Threading)适用于 I/O 密集型任务 ✅ 多进程(Multiprocessing)适用于 CPU 密集型任务 ✅ 线程池和进程池的使用 ✅ 异步编程(AsyncIO)提高 I/O 任务的并发性
一、为什么需要并发编程?
假设我们要下载 10 个文件,每个文件的下载时间大约是 5 秒:
-
顺序执行(串行):总时间
10 × 5 = 50 秒
- 并行执行(多线程或多进程):可以同时下载多个文件,减少总耗时
Python 提供了 三种主要的并发编程方式:
并发方式 |
适用场景 |
多线程(Threading) |
I/O 密集型任务,如网络爬取、文件 I/O |
多进程(Multiprocessing) |
CPU 密集型任务,如数学计算、图像处理 |
异步编程(AsyncIO) |
适用于高并发的 I/O 任务,如爬取 API |
二、Python 多线程(Threading)
1. 多线程的基本用法
Python threading
模块允许我们创建多个线程,让任务可以并发执行。
import threading
import time
def task(name):
print(f"{name} 开始执行")
time.sleep(2) # 模拟耗时任务
print(f"{name} 执行完成")
# 创建多个线程
threads = []
for i in range(5):
thread = threading.Thread(target=task, args=(f"线程 {i+1}",))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
print("所有任务完成!")
2. 代码解析:
✅ threading.Thread(target=task, args=(name,))
:创建线程
✅ thread.start()
:启动线程
✅ thread.join()
:等待线程执行完成
???? 多线程适用于 I/O 密集型任务,如:
- 网络请求
- 文件读写
- 数据库操作
三、Python 多进程(Multiprocessing)
由于 GIL(全局解释器锁) 限制,Python 的多线程 无法真正实现 CPU 并行计算,因此 对于 CPU 密集型任务(如数学计算、图像处理),应使用 multiprocessing
进行多进程计算。
1. 多进程的基本用法
import multiprocessing
import time
def compute(n):
print(f"计算 {n} 的平方...")
time.sleep(2) # 模拟计算
print(f"{n} 的平方是 {n**2}")
# 创建多个进程
processes = []
for i in range(5):
process = multiprocessing.Process(target=compute, args=(i+1,))
processes.append(process)
process.start()
# 等待所有进程完成
for process in processes:
process.join()
print("所有计算任务完成!")
2. 代码解析:
✅ multiprocessing.Process(target=compute, args=(i,))
:创建进程
✅ process.start()
:启动进程
✅ process.join()
:等待进程执行完成
???? 多进程适用于 CPU 密集型任务,如:
- 复杂数学计算
- 图像处理
- 大规模数据分析
四、线程池与进程池(ThreadPoolExecutor & ProcessPoolExecutor)
如果需要执行大量任务,可以使用 线程池(ThreadPoolExecutor)或进程池(ProcessPoolExecutor),自动管理线程/进程的创建和回收。
1. 线程池示例(适用于 I/O 任务)
from concurrent.futures import ThreadPoolExecutor
import time
def download(file):
print(f"正在下载 {file}...")
time.sleep(3) # 模拟下载
print(f"{file} 下载完成!")
files = ["文件1", "文件2", "文件3", "文件4", "文件5"]
# 使用线程池
with ThreadPoolExecutor(max_workers=3) as executor:
executor.map(download, files)
print("所有任务完成!")
2. 进程池示例(适用于 CPU 计算)
from concurrent.futures import ProcessPoolExecutor
def compute(n):
return n * n
numbers = [1, 2, 3, 4, 5]
# 使用进程池
with ProcessPoolExecutor(max_workers=3) as executor:
results = executor.map(compute, numbers)
print(list(results)) # 输出 [1, 4, 9, 16, 25]
✅ 线程池 vs 进程池
方式 |
适用场景 |
ThreadPoolExecutor |
I/O 任务,如爬取网页、文件处理 |
ProcessPoolExecutor |
计算密集型任务,如数学运算、图像处理 |
五、Python 异步编程(AsyncIO)
如果需要处理 高并发的 I/O 任务(如 API 请求、数据库操作),可以使用 asyncio
1. asyncio
示例(模拟网络请求)
import asyncio
async def fetch_data(url):
print(f"正在爬取 {url}...")
await asyncio.sleep(2) # 模拟 I/O 请求
print(f"{url} 爬取完成!")
async def main():
urls = ["网站1", "网站2", "网站3"]
tasks = [fetch_data(url) for url in urls]
await asyncio.gather(*tasks) # 并行执行任务
asyncio.run(main())
✅ 适用于:
- 爬取 API 数据
- 处理异步数据库操作
- 高并发请求
六、总结
在本篇博客中,我们学习了 如何使用 Python 进行并发编程:
方式 |
适用场景 |
多线程(Threading) |
I/O 任务(爬取网页、文件操作) |
多进程(Multiprocessing) |
CPU 计算(数学运算、数据分析) |
线程池(ThreadPoolExecutor) |
自动管理线程,适用于 I/O |
进程池(ProcessPoolExecutor) |
自动管理进程,适用于计算 |
异步编程(AsyncIO) |
高并发 API 请求 |
???? 选择正确的并发方式,可以大幅提高程序的运行效率! ????
希望本篇博客能帮助你掌握 Python 的并发编程,让你的代码执行更快、更高效!????