чтение очень большого файла, где формат не зависит от новой строки - PullRequest
1 голос
/ 11 ноября 2010

Мой код Python поддерживает чтение и запись данных в формате файла, созданном другими пользователями, который называется BLT формат . Формат BLT - это пробел и независимая от новой строки, поскольку новая строка обрабатывается так же, как и другие пробелы. Первичной записью в этом формате является «бюллетень», который заканчивается на «0», например,

1 2 3 0

Поскольку формат не зависит от новой строки, его также можно записать как

1 2
3 0

Или в одной строке может быть несколько бюллетеней:

1 2 3 0 4 5 6 0

Эти файлы могут быть очень большими, поэтому я не хочу читать весь файл в память. Строковое чтение является сложным, поскольку данные не основаны на строках. Каков хороший способ обработки этих файлов эффективным способом памяти?

Ответы [ 2 ]

3 голосов
/ 11 ноября 2010

Для меня самый простой способ решить эту проблему - с помощью генераторов.

def tokens(filename):
    with open(filename) as infile:
        for line in infile:
            for item in line.split():
                yield int(item)

def ballots(tokens):
    ballot = []
    for t in tokens:
        if t:
            ballot.append(t)
        else:
            yield ballot
            ballot = []

t = tokens("datafile.txt")

for b in ballots(t):
    print b

Я вижу, @katrielalex опубликовал решение по использованию генераторов, когда я публиковал свои.Разница между нашими заключается в том, что я использую два отдельных генератора, один для отдельных токенов в файле и один для конкретной структуры данных, которую вы хотите проанализировать.Первый передается последнему в качестве параметра, основная идея которого заключается в том, что вы можете написать функцию типа ballots() для каждой структуры данных, которую вы хотите проанализировать.Вы можете либо перебрать все, что было получено генератором, либо вызвать next() на любом генераторе, чтобы получить следующий токен или бюллетень (будьте готовы к исключению StopIteration, когда вы закончите, или напишите генераторам для генерации значения часовогонапример, None, когда у них заканчиваются реальные данные, и проверьте это).

Было бы довольно просто обернуть все это в классе.На самом деле ...

class Parser(object):

    def __init__(self, filename):

        def tokens(filename):
            with open(filename) as infile:
                for line in infile:
                    for item in line.split():
                        yield int(item)

        self.tokens = tokens(filename)

    def ballots(self):
        ballot = []
        for t in self.tokens:
            if t:
                ballot.append(t)
            else:
                yield ballot
                ballot = []

p = Parser("datafile.txt")

for b in p.ballots():
    print b
1 голос
/ 11 ноября 2010

Использовать генератор :

>>> def ballots(f):
...     ballots = []
...     for line in f:
...             for token in line.split():
...                     if token == '0':
...                             yield ballots
...                             ballots = []
...                     else:
...                             ballots.append(token)

. Он будет считывать файл построчно, разбивать все пробелы и добавлять токены в строке один за другим в список.Всякий раз, когда достигается ноль, этот бюллетень yield редактируется, а список сбрасывается на пустой.

...