StringIO ведет себя иначе при инициализации из буфера, в отличие от записи данных в него построчно - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь прочитать некоторые данные и разобрать их как CSV. Данный формат данных содержит причудливую первую строку, от которой мне сначала нужно избавиться.

delimiter = None
with open('data.csv', 'r', encoding='latin1') as fd:
    input1 = io.StringIO(fd.read())

with open('data.csv', 'r', encoding='latin1') as fd:
    input2 = io.StringIO()
    for line in fd:
        if line.startswith('sep='):
            delimiter = line[4]
        else:
            input2.write(line)

with open('data.csv', 'r', encoding='latin1') as fd:
    buf = ''
    for line in fd:
        if line.startswith('sep='):
            delimiter = line[4]
        else:
            buf += line
    input3 = io.StringIO(buf)

В случае, если я действительно добавлю в эту первую строку, то input1.getvalue () == input2.getvalue () == input3.getvalue (). А если нет, то по крайней мере input2.getvalue () == input3.getvalue ().

Затем идет бит CSV:

inputReader = csv.DictReader(inputX, delimiter=delimiter or ';')
for row in inputReader:
    print(row)

Это работает для input1, но из-за в дурацкой первой строке он запутывает имена столбцов, как и ожидалось.

Работает для input3 с правильными именами столбцов. Мне любопытно, почему for l oop не возвращает никаких результатов для input2. В чем разница между input2 и input3 в этой точке?

1 Ответ

1 голос
/ 06 апреля 2020

input2 располагается в конце «файла», тогда как построение StringIO из строки непосредственно помещает позицию файла в начало.

Чтобы исправить код input2, ищите вернуться к началу, как только вы закончите писать:

input2.seek(0)
...