Python останавливается при многократной обработке моего CSV-файла объемом 1 ГБ - PullRequest
1 голос
/ 06 января 2010

У меня есть два файла:

  1. metadata.csv: содержит идентификатор, имя поставщика, имя файла и т. Д.
  2. hashes.csv: содержит идентификатор, за которым следует хеш Этот идентификатор, по сути, является своего рода внешним ключом, связывающим метаданные файла с его хешем.

Я написал этот скрипт, чтобы быстро извлечь все хэши, связанные с конкретным поставщиком. Вырубается до того, как завершит обработку hashes.csv

stored_ids = []

# this file is about 1 MB
entries = csv.reader(open(options.entries, "rb"))

for row in entries:
  # row[2] is the vendor
  if row[2] == options.vendor:
    # row[0] is the ID
    stored_ids.append(row[0])

# this file is 1 GB
hashes = open(options.hashes, "rb")

# I iteratively read the file here,
# just in case the csv module doesn't do this.
for line in hashes:

  # not sure if stored_ids contains strings or ints here...
  # this probably isn't the problem though
  if line.split(",")[0] in stored_ids:

    # if its one of the IDs we're looking for, print the file and hash to STDOUT
    print "%s,%s" % (line.split(",")[2], line.split(",")[4])

hashes.close()

Этот скрипт получает около 2000 записей через hashes.csv, прежде чем он остановится. Что я делаю неправильно? Я думал, что обрабатывал это построчно.

пс. CSV-файлы - это популярный формат HashKeeper, а файлы, которые я анализирую, - это хеш-наборы NSRL. http://www.nsrl.nist.gov/Downloads.htm#converter

ОБНОВЛЕНИЕ: рабочий раствор ниже. Спасибо всем, кто прокомментировал!

entries = csv.reader(open(options.entries, "rb"))   
stored_ids = dict((row[0],1) for row in entries if row[2] == options.vendor)

hashes = csv.reader(open(options.hashes, "rb"))
matches = dict((row[2], row[4]) for row in hashes if row[0] in stored_ids)

for k, v in matches.iteritems():
    print "%s,%s" % (k, v)

Ответы [ 4 ]

3 голосов
/ 06 января 2010

"Craps out" - не очень хорошее описание. Что оно делает? Это поменяется? Заполнить всю память? Или просто жрет процессор, ничего не делая?

Однако, просто для начала, используйте словарь, а не список для stored_ids. Поиск в словаре обычно выполняется за O (1), а поиск в списке - O (n).

Редактировать: Вот тривиальный микро-тест:

$ python -m timeit -s "l=range(1000000)" "1000001 in l"
10 loops, best of 3: 71.1 msec per loop
$ python -m timeit -s "s=set(range(1000000))" "1000001 in s"
10000000 loops, best of 3: 0.174 usec per loop

Как видите, набор (который имеет те же характеристики производительности, что и dict) выполняет поиск среди миллиона целых чисел более чем в 10000 раз быстрее, чем аналогичный список (намного меньше микросекунды против почти 100 миллисекунд на поиск) , Учтите, что такой поиск происходит для каждой строки вашего файла объемом 1 ГБ, и вы понимаете, насколько серьезной может быть проблема.

0 голосов
/ 06 января 2010

Поиск в массиве занял O (n), поэтому используйте dict вместо

stored_ids = dict((row[0],1) for row in entries if row[2] == options.vendor)

Или используйте набор

a=set(row[0] for row in entries if row[2] == options.vendor)
b=set(line.split(",")[0] for line in hashes)
c=a.intersection(b)

в c вы найдете только строки для обоих хэшей, а csv

0 голосов
/ 06 января 2010

Пожалуйста, объясните, что вы подразумеваете под остановкой? зависает или выходит? Есть ли ошибка трассировки?

a) Сбой на любой строке без ","

>>> 'hmmm'.split(",")[2]
Traceback (most recent call last):
  File "<string>", line 1, in <string>
IndexError: list index out of range

б) почему вы разбиваете строку несколько раз, вместо этого сделайте это

tokens = line.split(",")

if len(tokens) >=5 and tokens[0] in stored_ids:
    print "%s,%s" % (tokens[2], tokens[4])

в) создайте дикт для сохраненных_данных, поэтому токены [0] в сохраненном_иде будут быстрыми

d) оберните свой внутренний код в try / exept и посмотрите, есть ли ошибки

e) где вы запускаете его в командной строке или в какой-нибудь IDE?

0 голосов
/ 06 января 2010

Этот код умрет на любой строке, которая не имеет по крайней мере 4 запятых; например, он умрет на пустой строке. Если вы уверены, что не хотите использовать csv reader, то хотя бы перехватите IndexError на line.split(',')[4]

...