Удалите пустой вывод, добавленный ленивым методом для чтения больших файлов - PullRequest
0 голосов
/ 21 июня 2011

Я использую Ленивый метод для чтения больших файлов, чтобы извлечь информацию из текстовых файлов и сохранить ее в базе данных.

def read_in_chunks(file_object, chunk_size=1024):
"""Lazy function (generator) to read a file piece by piece.
Default chunk size: 1k."""
while True:
    data = file_object.read(chunk_size)
    if not data:
        break
    yield data


f = open('really_big_file.dat')
for piece in read_in_chunks(f):
    process_data(piece) 

Проблема в том, что если я изменю process_data (кусок), например:

for data in piece:
    data = regex.findall(str(data)) 
    cursor.execute('INSERT INTO table (Title) VALUES (?)', data)

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

   for data in piece:
        data = regex.findall(str(data)) 
        if (data != ""):
             cursor.execute('INSERT INTO table (Title) VALUES (?)', data[1])

Но в информации, которую я извлекаю, есть некоторые действительные "пробелы" (когда в некоторых полях нет определенной информации. Как я могу избежать этого пробела между кусками ??? Я знаю, что это не проблема с Я извлекаю информацию, потому что, если я извлекаю файлы меньшего размера без использования ленивого метода, у меня нет этой проблемы, но у меня есть определенные файлы, которые намного больше, и они работают очень медленно без ленивого метода.

Спасибо

Ответы [ 2 ]

1 голос
/ 21 июня 2011

Есть несколько проблем с тем, что у вас есть. Если вы используете findall, то data может быть списком строк. Это не очень хорошо вписывается в базу данных.

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

попробуйте что-то вроде этого:

left_over = ''
for piece in read_in_chunks(f):
    left_over += piece
    next_start = 0
    for m in regex.finditer(left_over):
        data = m.group(0)
        next_start = m.end() + 1
        cursor.execute('INSERT INTO table (Title) VALUES (?)', data)
    left_over = left_over[next_start:]
0 голосов
/ 21 июня 2011

В дополнение к ответу @ Gerrat, вот пример того, как chunk_size может нарушить ваш поиск по регулярному выражению:

>>> from cStringIO import StringIO
>>> import re
>>> def chunker(f, chunk_size=10):
...     while True:
...         data = f.read(chunk_size)
...         if not data:
...             break
...         yield data
>>> pattern = re.compile(r"[a-zA-Z]{3}\d{3}")
>>> text = "Abc123 def456 ----------   ghi789"
>>> # on the full dataset, it's fine
... pattern.findall(text)
['Abc123', 'def456', 'ghi789']
>>> # but on chunks ...
... for data in chunker(StringIO(text)):
...     print "data: %r" % data
...     print "matches: %r" % pattern.findall(data)
data: 'Abc123 def'
matches: ['Abc123']
data: '456 ------'
matches: []
data: '----   ghi'
matches: []
data: '789'
matches: []

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

...