核心问题是多个生成器任务被错误地串行执行,因迭代器被复用或未独立初始化;应确保每次任务调用生成器函数获取新实例,避免共享耗尽的迭代器,协程中需区分同步与异步生成器。

核心问题在于:多个生成器任务被串行执行,不是因为逻辑必须串行,而是迭代器对象被错误复用或未独立初始化,导致本可并发的流程被迫排队。
确认迭代器是否被意外共享
生成器对象只能遍历一次。如果多个任务共用同一个生成器实例(比如定义在循环外、被反复传入),后续任务拿到的是已耗尽的迭代器,直接跳过执行。
- 检查生成器是否在循环体外创建,例如
gen = my_generator()写在for或while外部 - 确认函数返回的是生成器函数(如
def gen(): yield ...),而不是调用后返回的生成器对象(gen()) - 若需多次使用,应每次调用生成器函数(
my_generator()),而非复用my_generator()的返回值
避免在循环中隐式消耗迭代器
常见陷阱是把生成器传给 list()、sum()、any() 等函数后,再试图二次遍历——此时迭代器已空。
宝塔面板11.3.0是一款针对Linux服务器设计的可视化管理工具,通过重构核心模块实现资源占用显著降低,尤其适合低配置服务器环境。它将复杂的命令行操作转化为直观的图形界面,帮助开发者快速完成网站部署、环境配置及日常运维工作,无需专业技术背景即可高效管理服务器。
- 不要对同一生成器对象做多次消费操作:
data = my_gen(); list(data); sum(data)是错的 - 需要多次使用时,要么转为列表(内存允许前提下),要么用
itertools.tee()拆分: gen = my_generator(); a, b = itertools.tee(gen, 2)
批量任务应独立初始化生成器
当用循环启动多个异步或并行任务(如 asyncio.create_task() 或 ProcessPoolExecutor.submit()),每个任务必须拥有自己的生成器实例。
- 错误写法:
gen = data_stream(); [process(gen) for _ in range(5)]—— 五个任务争抢同一个生成器 - 正确写法:
[process(data_stream()) for _ in range(5)]—— 每次都新建生成器 - 若生成器构造开销大,可封装为工厂函数:
lambda: data_stream(),再由各任务调用
协程场景下注意生成器与 async/await 的混用边界
普通生成器(yield)不等于异步生成器(async def ... await ... yield)。混用会导致阻塞或调度失效。
- 同步生成器不能直接用于
async for;反之亦然 - 若需在协程中逐项消费数据,用
async def async_generator()替代普通生成器 - 同步生成器数据量大时,可用
loop.run_in_executor()包装,避免阻塞事件循环










