Уменьшение использования памяти при сравнении двух итерируемых


Я меняю код, который записывает данные в БД, поэтому у меня есть дамп (текстовый файл) в более ранней перспективе для сравнения, чтобы убедиться, что мои изменения не лажануться. Здесь идет:

def dbcheck(cursor):
    dbresult = list()
    cursor.execute("SELECT COLUMN FROM TABLE")
    for item in cursor.fetchall():
        line = item[0] + "\n"
        dbresult.append(line)
    with open(dbdump) as f:
        for n, line in enumerate(f):
            if line != dbresult[n]:
                print("DB content does not match original data!")

Этот код работает нормально, но я боюсь, что dbresult может вырасти очень большой, поэтому ищу менее рискованный способ сделать это. Я также любопытно, что еще можно улучшить.

[заметка на полях] я оставил обработка исключений для простоты/ясности.



942
5
задан 5 апреля 2011 в 10:04 Источник Поделиться
Комментарии
3 ответа

Это должно сделать это:

def dbcheck(cursor):
cursor.execute("SELECT COLUMN FROM TABLE")
with open(dbdump) as f:
for item in cursor:
if f.readline() != item + '\n'
print("DB content does not match original data!")

Не нужно читать либо всю колонку, ни весь файл перед итерацией.

5
ответ дан 6 апреля 2011 в 07:04 Источник Поделиться

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

def dbcheck(cursor):
cursor.execute("SELECT COLUMN FROM TABLE")
with open(dbdump) as f:
for item, line in zip(cursor, f):
if line != item[0] + '\n':
print("DB content does not match original data!")

Если используется Python 2.х использовать модуле itertools.izip функций вместо молнии. молния ставит все на огромный список, который не будет очень эффективным.

4
ответ дан 5 апреля 2011 в 10:04 Источник Поделиться

Вы можете использовать модуле itertools.izip функций, чтобы избежать чтения все данные перед итерацией. Кроме того, эта версия тут же распадается на поиске проблемы:

import itertools as it
def dbcheck(cursor):
with open(dbdump) as f:
cursor.execute("SELECT COLUMN FROM TABLE")
for fline, dbrec in it.izip(f, cursor):
if fline.strip() != dbrec[0]:
print("DB content does not match original data!")
break

Вот версии, которая сообщает Номер строки файла, вместе с несовпадающими данными, а продолжается для всех строк в файле. Также обратите внимание, что это не вызов print в качестве функции, а использовать скобки для группировки выражений создает строку для печати (в Python 3.х его зовет печати как функция):

import itertools as it
def dbcheck(cursor):
with open(dbdump) as f:
cursor.execute("SELECT COLUMN FROM TABLE")
for lineno, fline, dbrec in it.izip(it.count(), f, cursor):
if fline.strip() != dbrec[0]:
print("Line %d: File: %s, DB: %s" %
(lineno,
fline.strip(),
dbrec[0].strip()))

Кроме того, в Python 3, функция "молния" такая же, как itertools.zip я думаю.

1
ответ дан 6 апреля 2011 в 09:04 Источник Поделиться