#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