重置 csv.DictReader(StringIO.StringIO(某字符串))

1 投票
1 回答
2754 浏览
提问于 2025-04-17 18:45

我正在使用Python的csv.DictReader,但我用一个字符串来初始化它,像这样:

dict_reader = csv.DictReader(StringIO.StringIO(some_string))

有没有办法重置DictReader的迭代器,这样我就可以多次使用它?我不想重新解析这个字符串,因为那样可能会很耗费资源。

1 个回答

6

你可能已经知道,初始化这段代码:

dict_reader = csv.DictReader(StringIO.StringIO(some_string))

其实并没有从 StringIO.StringIO 实例中读取任何内容。dict_reader 只有在你开始提取行的时候才会开始读取,它是逐行读取输入的。换句话说,它只会读取你请求的行数。下面是一个例子:

#! /usr/bin/env python
import csv
try:
    from StringIO import StringIO   # Python 2.x
except ImportError:
    from io import StringIO         # Python 3.x

test_string = """name,value
foo,1
bar,2
"""

string_io = StringIO(test_string)
# 
# Position is 0 i.e. the beginning of the string.
# 
print("Position: {}".format(string_io.tell()))

dict_reader = csv.DictReader(string_io)
#
# Position is still 0. Nothing has been read.
#
print("Position: {}".format(string_io.tell()))
#
# Now we start reading from string_io
#
for row in dict_reader:
    print(row)
    #
    # Position increases every time you read 
    # a row using dict_reader.
    #
    print("Position: {}".format(string_io.tell()))

这段代码会打印:

Position: 0
Position: 0
{'name': 'foo', 'value': '1'}
Position: 17
{'name': 'bar', 'value': '2'}
Position: 23

在这一切结束时,string_io 的当前位置会指向字符串的末尾。所以,即使你可以重用 dict_reader,你也必须先将位置移回 string_io 的开头,然后重新开始扫描。实际上,在上面的代码之后,你可以这样做:

string_io.seek(0)
for row in dict_reader:
    print(row)
    print("Position: {}".format(string_io.tell()))

这个 for 循环会打印以下内容:

{'name': 'name', 'value': 'value'}
Position: 11
{'name': 'foo', 'value': '1'}
Position: 17
{'name': 'bar', 'value': '2'}
Position: 23

注意,dict_reader 现在把 string_io 的第一行当作数据来处理,而不是用它来决定字段的名称。此外,dict_reader 本身并不会保存它扫描过的所有行。一旦一行数据传递给你,它就不再通过 dict_reader 可用。你可以从 csv.DictReader.next() 的定义中看到这一点,具体可以查看 csv.pyReader_iternext()_csv.c 中的定义。因此,正如评论中所建议的,最好自己把这些行存储起来。

撰写回答