Эффективный способ чтения / записи / синтаксического анализа больших текстовых файлов (Python) - PullRequest
1 голос
/ 21 декабря 2011

Скажем, у меня нелепо большой текстовый файл.Я бы не подумал, что мой файл вырастет больше, чем ~ 500 МБ, но ради масштабируемости и моего собственного любопытства предположим, что он порядка нескольких гигов.

Моя конечная цель - сопоставить его смассив предложений (разделенных '?' '!' '.' и для всех намерений и целей ';') и каждое предложение к массиву слов.Затем я собирался использовать numpy для некоторого статистического анализа.

Каков самый масштабируемый способ сделать это?

PS: я думал переписать файл, чтобы в нем было одно предложениелинии, но я столкнулся с проблемами при попытке загрузить файл в память.Я знаю решение, в котором вы считываете фрагменты данных в одном файле, манипулируете ими и записываете их в другой, но это кажется неэффективным для дисковой памяти.Я знаю, что в настоящее время большинство людей не будут беспокоиться об использовании 10-гигабайтного пустого пространства, но кажется, что должен быть способ прямого редактирования фрагментов файла.

1 Ответ

5 голосов
/ 21 декабря 2011

Моей первой мыслью было бы использовать потоковый парсер: в основном вы читаете в файле по частям за раз и выполняете статистический анализ по ходу работы.Обычно это делается с помощью языков разметки, таких как HTML и XML, поэтому вы найдете множество синтаксических анализаторов для этих языков, в том числе в стандартной библиотеке Python.Простой парсер предложений - это то, что вы можете написать сами;например:

import re, collections
sentence_terminator = re.compile(r'(?<=[.!?;])\s*')
class SentenceParser(object):
    def __init__(self, filelike):
        self.f = filelike
        self.buffer = collections.deque([''])
    def next(self):
        while len(self.buffer) < 2:
            data = self.f.read(512)
            if not data:
                raise StopIteration()
            self.buffer += sentence_terminator.split(self.buffer.pop() + data)
        return self.buffer.popleft()
    def __iter__(self):
        return self

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

После анализатора потока я подумалбудет карта памяти файл.Таким образом, вы могли бы пройти и заменить пробел, который (предположительно) следует за каждым разделителем предложения новой строкой;после этого каждое предложение будет начинаться с новой строки, и вы сможете открыть файл и использовать цикл readline() или for, чтобы пройти по нему строка за строкой.Но вам все равно придется беспокоиться о многострочных предложениях;Кроме того, если любой терминатор предложения является , а не , за которым следует символ пробела, вам придется вставить новую строку (вместо замены чего-либо другим), и это может быть ужасно неэффективно для большого файла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...