Как оптимизировать поиск большого файла в Python

#python #file #search #optimization

#python #файл #Поиск #оптимизация

Вопрос:

У меня есть большой файл, содержащий около 8 миллионов строк имен файлов, и я пытаюсь выполнить поиск имен файлов, которые содержат определенное значение. Найти его — это нормально, но проблема в том, что я пытаюсь найти около 50 тысяч уникальных значений, а время, необходимое для поиска, огромно.

 with open('UniqueValueList.txt') as g:
    uniqueValues = g.read().splitlines()

outF = open("Filenames_With_Unique_Values.txt", "w")
with open('Filenames_File.txt') as f:
    fileLine = f.readlines()
    for line in fileLine:
        for value in uniqueValues:
            if value in line:
                outF.write(line)
outF.close()
  

Я не могу загрузить файл filenames в память, поскольку он слишком большой. Есть ли какой-либо другой способ оптимизировать этот поиск?

Комментарии:

1. Не пытайтесь прочитать весь файл (это то, что вы делаете с fileLine = f.readlines() ). Просто выполните итерацию по строкам файла: for line in f: . Если он все еще слишком медленный, вам, вероятно, придется улучшить способ поиска 50 тысяч различных значений в каждой строке.

2. Используете ли вы разветвленную систему, такую как Linux и Mac, или систему создания, такую как Windows? При разветвлении, как только файловые линии будут построены, вы можете запустить многопроцессорный пул и разделить значения для поиска среди них. Может быть, даже записать временный файл для каждого процесса, а затем объединить их в конце. Я не знаю, будет ли это быстрее, но со значениями 50k это может быть.

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

4. Первым делом было бы выйти из внутреннего цикла for после того, как вы нашли совпадение.

5. @Wups — это может отлично работать, но зависит от намерения OP. Если значение может соответствовать нескольким именам файлов, то поиск потребуется по всем строкам.

Ответ №1:

Мои две теории заключаются в том, чтобы (1) отобразить файл в памяти и использовать многострочное регулярное выражение для каждого поиска значений и (2) распределить работу на несколько подпроцессов. Я объединил их и получил следующее. Возможно, можно выполнить mmap в родительском файле и поделиться им, но я пошел простым путем и просто делал это в каждом подпроцессе, предполагая, что операционная система найдет для вас эффективный общий доступ.

 import multiprocessing as mp
import os
import mmap
import re

def _value_find_worker_init(filename):
    """Called when initializing mp.Pool to open an mmaped file in subprocesses.
    The file is `global mmap_file` so that the worker can find it.
    """
    global mmap_file
    filenames_fd = os.open(filename, os.O_RDONLY)
    mmap_file = mmap.mmap(filenames_fd, length=os.stat(filename).st_size,
        access=mmap.ACCESS_READ)

def _value_find_worker(value):
    """Return a list of matching lines in `global mmap_file`"""
    # multiline regex for findall
    regex = b"(?m)^.*?"   value   b".*?$"
    matched = re.compile(regex).findall(mmap_file)
    print(regex, matched)
    return matched

def find_unique():
    with open("UniqueValueList.txt", "rb") as g:
        uniqueValues = [line.strip() for line in g]
    with open('UniqueValueList.txt', "rb") as g:
        uniqueValues = [line.strip() for line in g]
    with mp.Pool(initializer=_value_find_worker_init,
            initargs=("Filenames_File.txt",)) as pool:
        matched_values = set()
        for matches in pool.imap_unordered(_value_find_worker, uniqueValues):
            matched_values.update(matches)
    with open("Filenames_With_Unique_Values.txt", "wb") as outfile:
        outfile.writelines(value   b"n" for value in matched_values)

find_unique()
  

Ответ №2:

Мы можем использовать объект file в качестве итератора. Итератор будет возвращать каждую строку одну за другой, которые могут быть обработаны. Это не приведет к считыванию всего файла в память и подходит для чтения больших файлов в Python.

Помогите себе с помощью этого понятного руководства, как прочитать огромный файл с помощью Python