
as_completed() 是 Python 并发编程中一个非常实用的函数,它的作用是:按照任务完成的顺序,而不是提交的顺序,来返回结果。
一、核心区别
场景对比
假设提交了 3 个任务,执行时间分别是:任务1(3秒)、任务2(1秒)、任务3(2秒)
| 方法 | 返回顺序 | 等待时间 |
|---|---|---|
as_completed() |
先完成的先返回:任务2 → 任务3 → 任务1 | 总耗时约 3 秒 |
wait() + 手动取结果 |
按提交顺序返回:任务1 → 任务2 → 任务3 | 总耗时约 3 秒 |
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
def task(name, delay):
time.sleep(delay)
return f"{name} 完成"
with ThreadPoolExecutor() as executor:
# 提交三个任务
futures = []
futures.append(executor.submit(task, "任务A", 3))
futures.append(executor.submit(task, "任务B", 1))
futures.append(executor.submit(task, "任务C", 2))
# 方式1:as_completed - 按完成顺序
print("=== as_completed ===")
for f in as_completed(futures):
print(f.result())
# 输出顺序:任务B完成 → 任务C完成 → 任务A完成
# 方式2:直接遍历 - 按提交顺序(会阻塞)
print("=== 直接遍历 ===")
for f in futures:
print(f.result()) # 任务A还没完成,会等待3秒
# 输出顺序:任务A完成 → 任务B完成 → 任务C完成
二、工作原理
源码简化
def as_completed(fs, timeout=None):
"""按完成顺序返回 Future"""
fs = set(fs)
while fs:
# 等待任何一个 Future 完成
done, _ = wait(fs, return_when=FIRST_COMPLETED)
for future in done:
yield future
fs.remove(future)
三、与其他方法的对比
| 方法 | 返回方式 | 阻塞特性 | 适用场景 |
|---|---|---|---|
for f in futures: f.result() |
按提交顺序 | 遇到未完成就阻塞 | 必须按顺序处理结果 |
as_completed(futures) |
按完成顺序 | 立即返回已完成的结果 | 结果处理顺序不重要 |
wait(futures) |
等待全部/任一完成 | 阻塞直到条件满足 | 需要批量等待 |
gather(*futures) |
按提交顺序返回列表 | 等待全部完成 | 需要一次性获取所有结果 |
备注: 其实as_completed 的意思就是:谁先做完,谁先被处理,不管当初谁先排队。