Python zip对象无法写入CSV文件的原因及版本差异探究
核心前提:Python中zip()返回的是一次性迭代器
Python 3.x里的zip()函数返回的是迭代器对象,而非容器(比如列表)。迭代器的本质是按需生成元素,一旦被完整遍历一次(比如转成list、循环遍历、用writerows读取),就会被"耗尽",后续再访问不会产生任何元素——这是所有失效版本的根本原因。
各版本生效/失效逻辑逐个解析
版本a) writer.writerows(zipped) → 失效
在代码里,执行converted_zipped = [[item for item in z] for z in list(zipped)]时,list(zipped)已经把zipped这个迭代器完整遍历了一遍,迭代器直接耗尽。后续再把zipped传给writerows(),里面已经没有任何元素可以写入,自然生成空CSV。
版本b) 遍历zipped循环 → 失效
和版本a原因完全一致:zipped迭代器已经被提前耗尽,循环根本不会执行,所以print无输出,也没有行被写入。
版本c) writer.writerows(list1) → 生效
list1是列表容器,不是迭代器,它可以被多次遍历。writerows()可以正常读取其中的每个子列表,作为CSV的一行写入文件。
版本d) writer.writerows(tuple_list) → 生效
tuple_list是元组组成的列表,同样属于容器型数据,支持多次遍历。writerows()能正确解析每个元组为CSV的一行内容。
版本e) writer.writerows(converted_zipped) → 生效
converted_zipped是通过list(zipped)把迭代器转换成的列表容器,已经将迭代器的所有元素一次性提取并保存下来,后续可以被writerows()正常遍历写入。
版本f) writer.writerow(zipped) → 失效
writerow()要求传入的是单行元素的可迭代对象,但这里直接传了已耗尽的迭代器:
- 迭代器本身已无元素,遍历后没有内容可写;
- 即使迭代器未耗尽,直接传入整个迭代器也会逻辑错误——
writerow()会把迭代器的每个元素当作单个单元格,而非一行的多个元素。
关于Python3.6旧代码正常运行的疑问
这和Python版本无关,核心差异是旧代码里没有提前遍历过zip迭代器。比如旧代码中可能没有像当前代码一样先执行list(zipped)的转换操作,而是直接把未被遍历过的zip对象传给writerows(),这时迭代器还未耗尽,就能正常写入内容。
内容的提问来源于Stack Exchange,提问作者qcabepsilon

