Чтение файла CSV кусками с помощью генератора - PullRequest
0 голосов
/ 10 ноября 2018

У меня есть большой CSV-файл, который мне нужно обработать, и это делается так (очень упрощенно):

import csv
from csv import excel

def _get_dialect():
    class CustomDialect(excel):
        delimiter = ','
    return CustomDialect()

class DictIter:
    def __init__(self):
        self.reader = csv.DictReader(open('test.csv'), 
                                     fieldnames=['col1', 'col2'], 
                                     dialect=_get_dialect())

    def __iter__(self):
        return self

    def __next__(self):
        return self.reader.__next__()

items = DictIter()
for item in items:
    print(item)

Есть лучшие способы сделать это, но это то, что у меня есть сейчас. Теперь я хотел бы разделить обработку на куски и найти это простое решение, которое должно работать для меня:

def gen_chunks(reader, chunksize=500):
    chunk = []
    for i, line in enumerate(reader):
        if (i % chunksize == 0 and i > 0):
            yield chunk
            del chunk[:]
        chunk.append(line)
    yield chunk

Однако мне не хватает знаний генератора, чтобы объединить эти два куска кода вместе. В основном я хочу что-то вроде этого:

import csv
from csv import excel

def gen_chunks(reader, chunksize=500):
    chunk = []
    for i, line in enumerate(reader):
        if (i % chunksize == 0 and i > 0):
            yield chunk
            del chunk[:]
        chunk.append(line)
    yield chunk

def _get_dialect():
    class CustomDialect(excel):
        delimiter = ','
    return CustomDialect()

class DictIter:
    def __init__(self):
        self.reader = csv.DictReader(open('test.csv'), 
                                     fieldnames=['col1', 'col2'], 
                                     dialect=_get_dialect())

    def __iter__(self):
        return self

    def __next__(self):
        for chunk in gen_chunks(self.reader):
            for item in chunk:
                yield item

items = DictIter()
for item in items:
    print(item)

Это может быть несколько неуклюжий подход, но я хочу реализовать обработку разбиения с минимальными изменениями в текущей структуре. То, чего я пытаюсь добиться, - это оставить текущую реализацию с классом итератора, но обрабатывать по одному куску за раз и получить следующий, когда я закончу с предыдущим.

1 Ответ

0 голосов
/ 10 ноября 2018

Ваше решение выглядит слишком сложным способом:

import csv

with open('test.csv',newline='') as f:
    reader = csv.DictReader(f,fieldnames=['col1', 'col2'])
    for item in reader:
        print(item)

Ваша порция по-прежнему возвращает один элемент за раз. Разделителем по умолчанию для диалекта excel является запятая, а excel является диалектом по умолчанию.

Примечание newline='' - это документированный способ открытия файла, переданного в csv объект чтения или записи.

Если у вас есть реальная причина для разделения (многопроцессорная обработка), вы должны указать это и показать , что попытается, если это не сработает.

...