Получение CSV-полей, а также необработанной строки из файла одновременно в Python - PullRequest
1 голос
/ 11 апреля 2020

У меня есть генератор, который выдает строки из файла CSV по одной, что-то вроде:

import csv

def as_csv(filename):
    with open(filename) as fin:
        yield from csv.reader(fin)

Однако мне нужно также захватить необработанную строку, возвращенную из файл, так как это должно быть сохранено в то же время.

Насколько я могу сказать, встроенный csv может использоваться на ad-ho c основе, что-то вроде этого:

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 объект ct и я возвращаем набор полей.

Может ли кто-нибудь предоставить реализацию some_coroutine или поочередно показать мне лучший механизм для получения нужных данных?

1 Ответ

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

Вы можете использовать itertools.tee, чтобы создать два независимых итератора из итерируемого файлового объекта, создать csv.reader из одного из них, а затем сжать другой итератор с ним для вывода:

from itertools import tee

def as_csv_and_raw(filename):
    with open(filename) as fin:
        row, raw = tee(fin)
        yield from zip(csv.reader(row), raw)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...