python多任务并行处理 _ Python并行处理多任务的高效实现方式
Python多任务并行需根据任务类型选择:I/O密集型使用ThreadPoolExecutor并配置连接池与合理worker数;CPU密集型使用ProcessPoolExecutor且函数需顶层定义;异步I/O使用asyncio配合异步库。注意避免GIL限制、序列化问题及线程安全,基准测试比理论更可靠。
Python 的多任务并行处理,说起来简单,实际坑不少。很多人第一反应是开多线程,但 CPython 的 GIL 让它对 CPU 密集型任务几乎没用;换成 multiprocessing 吧,进程开销、数据序列化、共享状态混乱,反倒可能更慢。所以关键不是“用哪个模块”,而是先判断你的任务到底属于哪种类型。
Python多任务应据任务类型选择:I/O密集用ThreadPoolExecutor(配连接池与合理worker数),CPU密集用ProcessPoolExecutor(函数需顶层定义),异步I/O用asyncio(配aiohttp等异步库)。

什么时候该用 concurrent.futures.ThreadPoolExecutor
它天生适合 I/O 密集型任务:HTTP 请求、文件读写、数据库查询。线程切换成本低,GIL 在等待 I/O 时会主动释放,所以实际效果接近并发。不过很多人栽在同一个坑里——用 requests.get() 批量调用时发现耗时没降,甚至更慢。原因不外乎两个:没设连接池和超时,或者并发数远远超过了系统能稳定维持的 socket 数量。
- 控制并发数,别硬写
max_workers=100。一个更稳妥的经验值是min(32, (os.cpu_count() or 1) + 4)。 - 一定要用
requests.Session()复用连接,否则每次get都新建 TCP 连接,开销直接爆炸。 - 另外,在
submit()的函数里直接操作全局变量或类实例属性,线程不安全。要么用threading.local(),要么加锁。
CPU 密集型任务必须用 concurrent.futures.ProcessPoolExecutor
multiprocessing.Pool 虽然也能用,但 ProcessPoolExecutor 的接口更统一(submit/as_completed),异常传播也更清晰。适合图像批量处理、数值计算、解析大型 JSON/XML、加密解密这类场景。
这里有几条容易翻车的细节:
- 传入的函数必须是模块顶层可导入的(不能是嵌套函数、lambda 或
@lru_cache包裹的函数),否则子进程反序列化时直接报AttributeError。 - 大对象别直接通过参数传——最好用
functools.partial预绑定,或者改用initializer+ 全局变量(注意进程间不共享内存)。 - 返回值会被 pickle,如果里面含不可序列化对象(如
threading.Lock、文件句柄),程序直接崩溃。
asyncio 不是“另一个并行方案”,而是协程调度器
它本身不并行,只并发;适合高吞吐、低延迟的 I/O 场景(比如同时处理几千个 WebSocket 连接)。但写法和调试的心智负担明显更高。
常见坑:time.sleep(1) 会阻塞整个事件循环,必须换成 await asyncio.sleep(1);同步库(如 requests、sqlite3)不能直接 await,得用 loop.run_in_executor 包一层。
- 别混用
asyncio和threading:比如在async def里开新线程,再试图 await 它——逻辑断裂,难以调试。 aiohttp替代requests是基本要求;数据库要选asyncpg、aiomysql等原生异步驱动。- 启动方式必须是
asyncio.run(main()),别用loop.create_task()后忘了loop.run_forever()——程序可能静默退出。
说到底,真正难的不是选哪个模块,而是判断任务类型、预估数据规模、测量真实瓶颈。一个 time.time() 包裹的基准测试,比所有理论都管用。别让“并行”成为性能优化的第一步——先确认它真是瓶颈所在。
Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。
极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。
















