我有一个生成器,可以一次从一个CSV文件中产生一行,类似于:
import csv
def as_csv(filename):
with open(filename) as fin:
yield from csv.reader(fin)
但是,我需要也捕获从文件返回的原始字符串,因为这需要同时保留。
据我所知,内置的csv
可以临时使用,如下所示:
import csv
def as_csv_and_raw(filename):
with open(filename) as fin:
for row in fin:
raw = row.strip()
values = csv.reader([raw])[0]
yield (values, raw)
...但这会为文件的每一行创建新的读取器和新的可迭代项,因此在具有数百万行的文件上,我担心性能会受到影响。
感觉就像我可以创建一个可以与主要功能进行交互的协程,以一种可以直接控制输入而不会丢失输入的方式产生已解析的字段,如下所示:
import csv
def as_csv_and_raw(filename):
with open(filename) as fin:
reader = raw_to_csv(some_coroutine())
reader.next()
for row in fin:
raw = row.strip()
fields = reader.send(raw)
yield fields, raw
def raw_to_csv(data):
yield from csv.reader(data)
def some_coroutine():
# what goes here?
raise NotImplementedError
[我并没有真正把头围在协程上,也没有使用yield
作为表达式,所以我不确定some_coroutine
中的内容,但目的是每次send
中的值都值通过csv.reader
对象运行,我得到了一组字段。
有人可以提供some_coroutine
的实现,还是可以向我展示一种获取所需数据的更好的机制?
您可以使用itertools.tee
从可迭代文件对象创建两个独立的迭代器,从其中一个创建csv.reader
,然后将另一个迭代器与它压缩以输出:
from itertools import tee
def as_csv_and_raw(filename):
with open(filename) as fin:
row1, row2 = tee(fin)
yield from zip(row1, csv.reader(row2))