Чтение огромного файла в Python

Ваша задача звучит так, как будто вы хотите попробовать watch : она может периодически запускать команду и показывать ее вывод. Используя его -g (--chgexit) (выход при изменении выхода), вы можете попытаться достичь желаемого. Я имею в виду следующее (не проверено):

#!/bin/bash
MON_DIR="/home/lab"
if [ -d $MON_DIR ] ; then
    echo "Directory exists."
    while true
    do
        watch -n 2 -g "ls ${MON_DIR}" > /dev/null
        echo "Content has changed."            
    done
else
    echo "Directory does not exists." > /dev/stderr
    exit $? > /dev/stderr
fi

Я подавляю вывод watch здесь, чтобы убедиться, что вы сможете увидеть сообщение. Вы также можете заменить бесконечный цикл (while true) чем-то, что может быть лучше прервано: Ctrl + C прервет watch и цикл перезапустит его. Таким образом, вам придется дважды нажать Ctr + C за короткий промежуток времени.

13
задан Jon Seigel 14 March 2010 в 20:25
поделиться

8 ответов

Если вам нужно только 200 из 50 миллионов строк, то чтение всего этого в память - пустая трата времени. Я бы отсортировал список ключей поиска и затем применил бинарный поиск к файлу, используя seek () или что-то подобное. Таким образом, вы не прочитали бы весь файл в память, что, я думаю, должно ускорить процесс.

11
ответ дан 1 December 2019 в 20:30
поделиться

Непонятно, что такое «список [указатель]». Однако учтите это.

from collections import defaultdict
keyValues= defaultdict(list)
targetKeys= # some list of keys
for line in fin:
    key, value = map( int, line.split())
    if key in targetKeys:
        keyValues[key].append( value )
4
ответ дан 1 December 2019 в 20:30
поделиться

Небольшая оптимизация ответа С.Лоттса:

from collections import defaultdict
keyValues= defaultdict(list)
targetKeys= # some list of keys as strings
for line in fin:
    key, value = line.split()
    if key in targetKeys:
        keyValues[key].append( value )

Поскольку мы используем словарь, а не список, ключи не должны быть числами. Это сохраняет операцию map () и преобразование строки в целое число для каждой строки. Если вы хотите, чтобы ключи были числами, выполните преобразование в конце, когда вам нужно сделать это только один раз для каждого ключа, а не для каждой из 50 миллионов строк.

7
ответ дан 1 December 2019 в 20:30
поделиться

Я бы использовал отображение памяти: http://docs.python.org/library/mmap. HTML .
Таким образом, вы можете использовать файл так, как будто он хранится в памяти, но ОС решает, какие страницы на самом деле следует прочитать из файла.

3
ответ дан 1 December 2019 в 20:30
поделиться

Вот рекурсивный двоичный поиск по текстовому файлу

import os, stat

class IntegerKeyTextFile(object):
    def __init__(self, filename):
        self.filename = filename
        self.f = open(self.filename, 'r')
        self.getStatinfo()

    def getStatinfo(self):
        self.statinfo = os.stat(self.filename)
        self.size = self.statinfo[stat.ST_SIZE]

    def parse(self, line):
        key, value = line.split()
        k = int(key)
        v = int(value)
        return (k,v)

    def __getitem__(self, key):
        return self.findKey(key)

    def findKey(self, keyToFind, startpoint=0, endpoint=None):
        "Recursively search a text file"

        if endpoint is None:
            endpoint = self.size

        currentpoint = (startpoint + endpoint) // 2

        while True:
            self.f.seek(currentpoint)
            if currentpoint <> 0:
                # may not start at a line break! Discard.
                baddata = self.f.readline() 

            linestart = self.f.tell()
            keyatpoint = self.f.readline()

            if not keyatpoint:
                # read returned empty - end of file
                raise KeyError('key %d not found'%(keyToFind,))

            k,v = self.parse(keyatpoint)

            if k == keyToFind:
                print 'key found at ', linestart, ' with value ', v
                return v

            if endpoint == startpoint:
                    raise KeyError('key %d not found'%(keyToFind,))

            if k > keyToFind:
                return self.findKey(keyToFind, startpoint, currentpoint)
            else:
                return self.findKey(keyToFind, currentpoint, endpoint)

Пример текстового файла, созданного в jEdit, похоже, работает:

>>> i = integertext.IntegerKeyTextFile('c:\\sampledata.txt')
>>> i[1]
key found at  0  with value  345
345

Это определенно можно улучшить, кэшируя найденные ключи и используя кеш для определения будущих начальных точек поиска.

3
ответ дан 1 December 2019 в 20:30
поделиться

Одной из возможных оптимизаций является небольшая буферизация с использованием опции sizehint в file.readlines (..) . Это позволяет загружать в память несколько строк общим объемом примерно sizehint байтов.

0
ответ дан 1 December 2019 в 20:30
поделиться

Если у вас есть какой-либо контроль над форматом файла, ответы «сортировка и двоичный поиск» верны. Суть в том, что это работает только с записями фиксированного размера и смещения (ну, я должен сказать, что это легко работает только с записями фиксированной длины).

С записями фиксированной длины вы можете легко искать () вокруг отсортированного файла в найди свои ключи.

2
ответ дан 1 December 2019 в 20:30
поделиться

Вам необходимо реализовать бинарный поиск с использованием seek ()

0
ответ дан 1 December 2019 в 20:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: