Самый эффективный способ разбора большого .csv в Python? - PullRequest
12 голосов
/ 01 февраля 2012

Я пытался посмотреть на другие ответы, но я все еще не уверен, как это сделать. У меня есть несколько очень больших файлов .csv (каждый может быть гигабайтом), и я хочу сначала получить метки их столбцов, потому что они не все одинаковые, а затем в соответствии с предпочтениями пользователя извлечь некоторые из этих столбцов с некоторыми критериями , Перед тем, как приступить к извлечению, я выполнил простой тест, чтобы увидеть, какой самый быстрый способ проанализировать эти файлы, и вот мой код:

def mmapUsage():
    start=time.time()
    with open("csvSample.csv", "r+b") as f:
        # memory-mapInput the file, size 0 means whole file
        mapInput = mmap.mmap(f.fileno(), 0)
        # read content via standard file methods
        L=list()
        for s in iter(mapInput.readline, ""):
            L.append(s)
        print "List length: " ,len(L)
        #print "Sample element: ",L[1]
        mapInput.close()
        end=time.time()
        print "Time for completion",end-start

def fileopenUsage():
    start=time.time()
    fileInput=open("csvSample.csv")
    M=list()
    for s in fileInput:
            M.append(s)
    print "List length: ",len(M)
    #print "Sample element: ",M[1]
    fileInput.close()
    end=time.time()
    print "Time for completion",end-start

def readAsCsv():
    X=list()
    start=time.time()
    spamReader = csv.reader(open('csvSample.csv', 'rb'))
    for row in spamReader:
        X.append(row)
    print "List length: ",len(X)
    #print "Sample element: ",X[1]
    end=time.time()
    print "Time for completion",end-start

И мои результаты:

=======================
Populating list from Mmap
List length:  1181220
Time for completion 0.592000007629

=======================
Populating list from Fileopen
List length:  1181220
Time for completion 0.833999872208

=======================
Populating list by csv library
List length:  1181220
Time for completion 5.06700015068

Так что, похоже, что библиотека csv, которую использует большинство людей, действительно намного медленнее, чем другие. Может быть, позже это окажется быстрее, когда я начну извлекать данные из файла CSV, но я пока не уверен в этом. Любые предложения и советы, прежде чем я начну внедрять? Большое спасибо!

Ответы [ 4 ]

16 голосов
/ 01 февраля 2012

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

Модуль CSV неоценим, если вы включаете любые текстовые данные, которые могут включать в себя больше «стандартного» синтаксиса CSV, чем просто запятые, особенно есливы читаете из формата Excel.Если у вас есть только строки типа «1,2,3,4», вы, вероятно, подойдете к простому разбиению, но если у вас есть строки, такие как «1,2, 'Hello, my name \' s fred '", высобираюсь сходить с ума, пытаясь разобрать это без ошибок.CSV также будет прозрачно обрабатывать такие вещи, как переводы строк в середине строки в кавычках.Простое for..in без CSV будет иметь проблемы с этим.

Модуль CSV всегда работал нормально для меня, читая Unicode-строки, если я использую его так:

f = csv.reader (codecs.open (filename, 'rU'))

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

3 голосов
/ 01 февраля 2012

Насколько вы заботитесь о санитарной обработке?

Модуль csv действительно хорош для понимания различных диалектов CSV-файлов и обеспечения того, что экранирование происходит правильно, но это определенно излишне ичасто может быть гораздо больше проблем, чем стоит (особенно если у вас есть юникод!)

Действительно наивная реализация, которая правильно экранирует \,, будет:

import re

def read_csv_naive():
    with open(<file_str>, 'r') as file_obj:
      return [re.split('[^\\],', x) for x in file_obj.splitlines()]

Если ваши данные простыэто будет отлично работатьЕсли у вас есть данные, которые могут нуждаться в дополнительном экранировании, модуль csv, вероятно, является вашей наиболее стабильной ставкой.

2 голосов
/ 29 сентября 2013

Чтобы прочитать большой CSV-файл, мы должны создать дочерний процесс для чтения фрагментов файла.Откройте файл, чтобы получить объект файлового ресурса.Создайте дочерний процесс с ресурсом в качестве аргумента.Прочитайте набор строк как кусок.Повторяйте вышеописанные 3 шага, пока не дойдете до конца файла.

from multiprocessing import Process

def child_process(name):
    # Do the Read and Process stuff here.if __name__ == '__main__':
    # Get file object resource.
    .....
    p = Process(target=child_process, args=(resource,))
    p.start()
    p.join()

Для кода перейдите по этой ссылке.Это поможет вам.http://besttechlab.wordpress.com/2013/12/14/read-csv-file-in-python/

1 голос
/ 01 февраля 2012

Ваши первые 2 метода НЕ разбирают каждую строку в полях.Способ csv состоит в разборе строк (НЕ совпадающих со строками!) Полей.

Вам действительно нужно создать список в памяти всех строк?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...