yield 是关键,它让生成器函数能边读边喂数据,避免把整个训练集一次性塞进内存;生成器惰性执行、节省内存,但仅可迭代一次、不可序列化,多进程需每个 worker 独立创建。

yield 是关键,它让生成器函数能边读边喂数据,避免把整个训练集一次性塞进内存。
训练时加载大文件总报 MemoryError?用 yield 替代 return
模型训练常需遍历百万级样本(如日志、图像路径、文本行),若用列表一次性读入:data = [process_line(line) for line in open("train.txt")],10GB 文件大概率直接崩。换成生成器函数,每次只 hold 一行或一个 batch 的内存:
-
yield让函数变成“暂停-恢复”状态机,不是返回值后就结束 - PyTorch 的
DataLoader或 TensorFlow 的tf.data.Dataset.from_generator都原生支持接收生成器对象 - 注意:生成器只能迭代一次,训练多 epoch 时得在每个 epoch 重新调用生成器函数(比如封装成
def train_gen(): ...,每次传train_gen())
next() 和 for 循环对生成器的行为差异
你手动调用 next() 会暴露底层细节,而 for 循环自动捕获 StopIteration —— 这在训练循环里很关键:
- 用
for sample in data_gen()安全,循环自然结束 - 手写
while True: try: x = next(gen) ... except StopIteration: break容易漏异常处理,尤其嵌套 generator 时容易提前终止 - 某些框架(如 Keras
model.train_on_batch)内部会反复调用next(),所以必须确保生成器逻辑能稳定产出,不能中途抛错
批量生成时别在 yield 前做重操作
生成器的惰性本质会被破坏,如果批量逻辑写错位置:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- ❌ 错误:先收集满 32 行再
yield batch→ 仍会短暂占用 32 行内存,且无法流式释放 - ✅ 正确:用内部缓冲区累积,但
yield后立刻清空;或更推荐用itertools.islice+ 外层生成器组合 - 警惕
list.append()累积、pandas.read_csv(..., chunksize=)返回的可迭代对象本身已是生成器,无需再包一层 yield
生成器无法被 pickle,跨进程会失败
这是最容易被忽略的硬伤,尤其在分布式训练或使用多进程 DataLoader(num_workers > 0)时:
立即学习“Python免费学习笔记(深入)”;
- 生成器对象不能序列化,worker 进程无法重建它 → 报
TypeError: can't pickle generator objects - 解决方案:把生成器逻辑写成普通函数,让每个 worker 自己调用该函数创建新生成器(即“每个进程一个实例”,而非共享一个生成器对象)
- 别试图用
functools.partial包装带状态的生成器——状态不会跨进程传递

















