Накладные расходы Python SequenceMatcher — 100% загрузка ЦП и очень медленная обработка
Вопрос
Я использую difflib для сравнения файлов в двух каталогах (версии за несколько лет подряд).Во-первых, я использую filecmp, чтобы найти файлы, которые были изменены, а затем итеративно использую difflib.SequenceMatcher, чтобы сравнить их и сгенерировать разницу в формате html, как объяснено. здесь.
Однако я обнаружил, что программа выполняется слишком долго, а Python использует 100% процессорного времени.Профилируя время, я обнаружил, что seqm.get_opcodes() звонок, который занимает все время.
Любое понимание будет оценено по достоинству.Спасибо !
Код:
#changed_set contains the files to be compared
for i in changed_set:
oldLines = open(old_dir +"/" + i).read()
newLines = open(new_dir +"/" + i).read()
seqm = difflib.SequenceMatcher(lambda(x): x in string.whitespace, oldLines, newLines)
opcodes = seqm.get_opcodes() #XXX: Lots of time spent in this !
produceDiffs(seqm, opcodes)
del seqm
Решение
Мой ответ - совершенно другой подход к проблеме:Попробуйте использовать систему контроля версий, например git, чтобы выяснить, как каталог менялся с течением времени.
Создайте репозиторий из первого каталога, затем замените его содержимое каталогом следующего года и зафиксируйте его как изменение.(или переместите каталог .git в каталог следующего года, чтобы сэкономить на копировании/удалении).повторить.
Затем запустите gitk, и вы сможете увидеть, что изменилось между любыми двумя ревизиями дерева.Либо просто изменился бинарный файл, либо с дифом текстовых файлов.
Другие советы
Вы также можете попробовать diff-match-patch
Библиотека, по моему опыту, это может быть в 10 раз быстрее.
РЕДАКТИРОВАТЬ: Пример мой другой ответ здесь
from diff_match_patch import diff_match_patch
def compute_similarity_and_diff(text1, text2):
dmp = diff_match_patch()
dmp.Diff_Timeout = 0.0
diff = dmp.diff_main(text1, text2, False)
# similarity
common_text = sum([len(txt) for op, txt in diff if op == 0])
text_length = max(len(text1), len(text2))
sim = common_text / text_length
return sim, diff