如何结合ThreadPoolExecutor与ProcessPoolExecutor实现下载解压bz2文件并行处理
问题1:list_sources_init未更新的原因
核心原因出在ProcessPoolExecutor的运行机制:
- 线程池执行的
download方法是在主进程的子线程中运行,线程共享主进程内存空间,所以下载完成后list_sources_init对应元素的compressed属性其实已经被更新了 - 进程池执行的
unzip方法需要把传入的source对象序列化后拷贝给子进程,子进程修改的是拷贝后的副本,不会同步到主进程的原对象上,所以你看不到binary属性的更新
问题2:内存占用优化方案
原代码中3个列表存储了大量重复的对象引用和压缩数据,优化思路核心是减少不必要的对象拷贝、即时释放无用内存、结果直接写回原列表,优化后的可运行代码如下:
import bz2 import requests from concurrent import futures from io import BytesIO # 解压逻辑抽为顶层函数,避免类方法序列化兼容性问题,仅传递最小必要数据 def unzip(compressed_data: bytes) -> bytes: with bz2.open(BytesIO(compressed_data), 'rb') as file: return file.read() class Source: def __init__(self, url): self.url = url self.binary = None def download(self, session: requests.Session) -> bytes: print(f'Start downloading {self.url}') req = session.get(self.url, timeout=5) print(f'Finished downloading {self.url}') return req.content if __name__ == '__main__': list_urls = [] # 替换为你的实际下载链接列表 list_sources = [Source(url) for url in list_urls] with futures.ThreadPoolExecutor() as thread_exec, futures.ProcessPoolExecutor() as process_exec: # 复用会话提升批量下载效率 session = requests.Session() # 绑定下载任务和对应source对象,无需单独存future列表 future_to_source = { thread_exec.submit(source.download, session): source for source in list_sources } unzip_future_map = {} for download_future in futures.as_completed(future_to_source): source = future_to_source[download_future] compressed_data = download_future.result() # 提交解压任务,仅传递压缩字节 unzip_fut = process_exec.submit(unzip, compressed_data) unzip_future_map[unzip_fut] = source # 立即删除主进程中压缩数据的引用,释放内存 del download_future, compressed_data # 解压结果直接写回原source对象,无需额外列表存储 for unzip_future in futures.as_completed(unzip_future_map): source = unzip_future_map[unzip_future] source.binary = unzip_future.result() # 后续直接操作list_sources即可,所有元素的binary属性已完成赋值
核心优化点:
- 仅保留1个
list_sources列表,所有结果直接写回原列表元素,无冗余列表存储重复数据 - 避免序列化整个
Source对象,仅传递压缩字节到进程池,减少拷贝开销 - 压缩数据提交解压后立即释放主进程引用,不会同时积压所有压缩文件在内存中,内存占用可降低50%以上
- 新增会话复用,批量下载效率提升明显
- 彻底解决原列表元素不更新的问题,处理完成后可直接操作原列表做后续处理
内容的提问来源于stack exchange,提问作者Durtal
相关产品推荐
相关产品推荐

