multiprocessing模块
Python的GIL限制了多进程并发,使用 multiprocessing 模块 开启多进程并行处理任务,让 Python 真正用上多核 CPU,速度暴涨!
多进程的优势在哪?
- CPU 全核利用:
multiprocessing可以用满你的 4核/8核 CPU; - pool.map() 轻松调度任务;
场景:对一个大文件夹的所有.txt文件进行批量处理
比如,你要统计每个文本文件中的关键词数量,或进行格式转换、数据提取。
1 import os 2 import time 3 from multiprocessing import Pool, cpu_count 4 5 script_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 6 7 # 要处理的文件夹路径 8 FOLDER_PATH = script_dir + "/txtfile" 9 10 # 定义你的文本处理逻辑 11 def process_file(file_path): 12 with open(file_path, "r", encoding="utf-8") as f: 13 content = f.read() 14 word_count = len(content.split()) 15 print(f"{os.path.basename(file_path)} 有 {word_count} 个单词") 16 return word_count 17 18 # 获取所有 txt 文件路径 19 def get_txt_files(folder): 20 return [os.path.join(folder, f) for f in os.listdir(folder) if f.endswith(".txt")] 21 22 def main(): 23 start = time.time() 24 files = get_txt_files(FOLDER_PATH) 25 26 # 创建进程池,核心数 = CPU 核心数 27 with Pool(processes=cpu_count()) as pool: 28 pool.map(process_file, files) 29 30 print(f"所有文件处理完成,用时 {time.time() - start:.2f} 秒") 31 32 if __name__ == "__main__": 33 main()
执行结果:
file1.txt 有 72 个单词
file2.txt 有 64 个单词
file3.txt 有 62 个单词
file4.txt 有 91 个单词
所有文件处理完成,用时 6.74 秒
那么有人要问,多进程总行了吧?多进程确实能绕过 GIL 的限制,利用多核 CPU,但多进程也有它的问题:
- 资源消耗大: 每个进程都有自己独立的内存空间,进程多了,内存消耗蹭蹭往上涨。
- 进程间通信复杂: 进程间数据共享和通信,比线程要麻烦不少。
- 上下文切换开销: 进程切换的开销,比线程切换更大。
所以,多进程也不是万能的,尤其是在 I/O 密集型 的任务面前,比如网络请求、文件读写等等,多进程的优势就没那么明显了。
这个时候可以考虑异步编程,使用asynico模块,是Python标准库,用于编写I/O操作代码。下面改用异步编程实现方法如下:
1 import os 2 import time 3 import asyncio 4 import aiofiles 5 6 script_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 7 8 # 要处理的文件夹路径 9 FOLDER_PATH = script_dir + "/txtfile" 10 11 # 异步处理单个文件 12 async def process_file(file_path): 13 async with aiofiles.open(file_path, "r", encoding="utf-8") as f: 14 content = await f.read() 15 word_count = len(content.split()) 16 print(f"{os.path.basename(file_path)} 有 {word_count} 个单词") 17 return word_count 18 19 # 获取所有 txt 文件路径 20 def get_txt_files(folder): 21 return [os.path.join(folder, f) for f in os.listdir(folder) if f.endswith(".txt")] 22 23 async def main(): 24 start = time.time() 25 files = get_txt_files(FOLDER_PATH) 26 27 # 并发执行所有文件处理任务 28 tasks = [process_file(file) for file in files] 29 await asyncio.gather(*tasks) 30 31 print(f"所有文件处理完成,用时 {time.time() - start:.2f} 秒") 32 33 if __name__ == "__main__": 34 asyncio.run(main())
运行结果:
file1.txt 有 72 个单词
file2.txt 有 64 个单词
file3.txt 有 62 个单词
file4.txt 有 91 个单词
所有文件处理完成,用时 0.01 秒
在I/O密集任务处理时,对比多进程,可见使用异步实现,耗时最短,性能有很大提升。
应用场景扩展:
- 批量爬虫:抓取网页/下载图片
- 多文件转换:如批量 PDF 转 TXT
- 数据处理:并行处理 CSV/日志文件
- CPU 密集型任务:图像识别、加密计算
作者:Jason
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
浙公网安备 33010602011771号