Python: ускорение re.sub для редактирования файлов (мультиобработка не помогает) - PullRequest
0 голосов
/ 06 июля 2018

Мне нужно отредактировать определенные слова из нескольких тысяч файлов. Существует отдельный справочный файл, содержащий около 50000 слов, которые необходимо удалить из файлов.

С кодом, который я написал, процесс займет недели, и мне нужно сделать его быстрее.

import glob, re, sys
from multiprocessing.dummy import Pool as ThreadPool

def redact_file(file):
    with open(file, 'r') as myfile:
        data=myfile.read()

        for word in words_to_redact:
            search_term = r"(?:\b)"+word+r"(?:\b)"
            data = re.sub(search_term, '#', data, flags=re.IGNORECASE)  #this seems to be the slow bit?

    with open(file+'_REDACTED', 'w') as file:
        file.write(data)


if __name__ == "__main__":
    words_to_redact = []
    with open ("words_to_redact.txt") as myfile:    #about 50,000 rows in this reference file
        words_to_redact=myfile.read().splitlines()

    input_files = glob.glob("input_*.txt")

    pool = ThreadPool(multiprocessing.cpu_count()) 
    pool.map(redact_file, input_files)

Использование мультиобработки, похоже, не помогает.

Я думаю, что проблема в производительности связана с вызовом re.sub 50000 раз для каждого файла. Поскольку при каждой итерации создается новая копия строки «данных», я думаю, что этот процесс ограничивается скоростью памяти / кэша.

Я думаю, что должен использовать re.sub, потому что использование regEx - единственный способ сопоставить слова.

Есть ли способ сделать re.sub без копии каждый раз или какой-нибудь другой способ сделать это быстрее?

1 Ответ

0 голосов
/ 06 июля 2018
  1. используйте re.compile() для компиляции шаблона один раз, а не каждый раз, когда вы выполняете поиск

  2. сложите все свои слова в большой шаблон.

Тогда ваш код может выглядеть так:

import re

words_to_redact = [ 'aa', 'bb', 'cc', etc...] # load 'em from file

patt = re.compile( r"(?:\b)(" + '|'.join( words_to_redact ) + r")(?:\b)" )

patt.sub( .. )  # you know what to do, need to call this only once (no loop)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...