Поиск файлов TXT в Python - PullRequest
1 голос
/ 22 июля 2011

Я новый программист, и мы работаем над проектом Graduate English, где мы пытаемся разобрать гигантский текстовый файл словаря (500 МБ). Файл настроен с html-подобными тегами. У меня есть 179 тегов автора, например. «[A>] Shakes. [/ A]» для Шекспира, и мне нужно найти каждое вхождение каждого тега, а затем написать этот тег и то, что следует в строке, пока я не доберусь до «[/ W]».

Моя проблема в том, что readlines () дает мне ошибку памяти (я полагаю, потому что файл очень большой), и я был в состоянии найти совпадения (но только один раз) и не смог заставить его смотреть мимо Первый матч Буду очень признателен за любую помощь

В текстовом файле нет новых строк, которые, по-моему, вызывают проблему. Эта проблема была решена. Я думал, что я включу код, который работал:

with open('/Users/Desktop/Poetrylist.txt','w') as output_file:
with open('/Users/Desktop/2e.txt','r') as open_file:
    the_whole_file = open_file.read()
    start_position = 0
    while True:
        start_position = the_whole_file.find('<A>', start_position)
        if start_position < 0:
            break
        start_position += 3
        end_position = the_whole_file.find('</W>', start_position)
        output_file.write(the_whole_file[start_position:end_position])
        output_file.write("\n")    
        start_position = end_position + 4

Ответы [ 6 ]

3 голосов
/ 22 июля 2011

После открытия файла итерируйте строки следующим образом:

input_file = open('huge_file.txt', 'r')
for input_line in input_file:
   # process the line however you need - consider learning some basic regular expressions

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

2 голосов
/ 22 июля 2011

Я не знаю регулярных выражений, но вы можете решить эту проблему без них, используя строковый метод find () и нарезку строк.

answer = ''

with open('yourFile.txt','r') as open_file, open('output_file','w') as output_file:
    for each_line in open_file:
        if each_line.find('[A>]'):
            start_position = each_line.find('[A>]')
            start_position = start_position + 3
            end_position = each_line[start_position:].find('[/W]')

            answer = each_line[start_position:end_position] + '\n'
            output_file.write(answer)

Позвольте мне объяснить, что происходит:

  1. Создать пустой список с помощью = [].Это будет держать ваши ответы.
  2. Используйте оператор with ...Это позволяет вам открывать ваш файл как псевдоним (я выбрал open_file).Это обеспечивает автоматическое закрытие вашего файла независимо от того, работает ли ваша программа правильно.
  3. Мы используем идиому 'for line in file:' для обработки файла по одной строке за раз.Переменная 'line' может быть названа как угодно (например, для x в файле, для pizza в файле) и всегда будет содержать каждую строку в виде строки.Когда он доходит до конца файла, он автоматически останавливается.
  4. оператор 'if each_line.find (' [A>] '):' просто проверяет, находится ли начальный тег в этой строке.Если это не так, ни один из следующего кода с отступом не будет запущен, и цикл перезапустится, перейдя к следующей строке.
  5. Мы используем нарезку строк, где мы можем вырезать часть строкимы хотим.Что мы делаем, это ищем первый тег по позиции (который мы уже знаем, находится в этой строке), затем ищем стоп-тег по позиции.Получив их, мы можем просто вырезать ту часть, которую хотим.
  6. Я усилил позицию двумя способами.1 Я добавил 3 к стартовой позиции, чтобы он пропустил [A>] - таким образом, вместо того, чтобы давать «[A>] ЭТО МОЯ СТРОКА ...», он просто дает «ЭТО МОЯ СТРОКА ...» Я тогдавыполнял поиск конечной позиции путем поиска ее первого вхождения ПОСЛЕ тега [A>], в том числе тег [/ W] встречается более одного раза в каждой строке.
  7. Мы устанавливаем ответ на фрагмент строки и символ новой строки ('\ n'), чтобы каждая строка отображалась в отдельной строке.Мы используем метод вывода .write ('stringToWrite') для записи каждой строки, по одной за раз.
1 голос
/ 22 июля 2011

Вы получаете ошибку памяти с readlines (), потому что учитывая размер файла, который вы, вероятно, читаете в большем количестве данных, чем ваша память может разумно обработать.Поскольку этот файл является файлом XML, вы должны быть в состоянии прочитать его iterparse (), который будет анализировать XML лениво, не занимая лишнюю память.Вот некоторый код, который я использовал для разбора дампов Википедии:

for event, elem in parser:
    if event == 'start' and root == None:
        root = elem
    elif event == 'end' and elem.tag == namespace + 'title':
        page_title = elem.text
        #This clears bits of the tree we no longer use.
        elem.clear()
    elif event == 'end' and elem.tag == namespace + 'text':
        page_text = elem.text
        #Clear bits of the tree we no longer use
        elem.clear()

        #Now lets grab all of the outgoing links and store them in a list
        key_vals = []


        #Eliminate duplicate outgoing links.
        key_vals = set(key_vals)
        key_vals = list(key_vals)

        count += 1

        if count % 1000 == 0:
            print str(count) + ' records processed.'
    elif event == 'end' and elem.tag == namespace + 'page':
        root.clear()

Вот как примерно это работает:

  1. Мы создаем парсер для прохождения по документу.

  2. Когда мы перебираем каждый элемент документа, мы ищем элементы с тегом, который вы ищете (в вашем примере это был 'A').

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

0 голосов
/ 23 июля 2011

Пожалуйста, проверьте следующий код:

import re

regx = re.compile('<A>.+?</A>.*?<W>.*?</W>')

with open('/Users/Desktop/2e.txt','rb')         as open_file,\
     open('/Users/Desktop/Poetrylist.txt','wb') as output_file:

    remain = ''

    while True:
        chunk = open_file.read(65536) # 65536 == 16 x 16 x 16 x 16
        if not chunk:  break
        output_file.writelines( mat.group() + '\n' for mat in regx.finditer(remain + chunk) )
        remain = chunk[mat.end(0)-len(remain):]

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

0 голосов
/ 22 июля 2011

Вместо анализа файла вручную, почему бы не проанализировать его как XML , чтобы лучше контролировать данные?Вы упомянули, что данные похожи на HTML, поэтому я предполагаю, что они могут быть проанализированы как XML-документ.

0 голосов
/ 22 июля 2011

Вы должны посмотреть на инструмент под названием "Grep". Вы можете дать ему образец для сопоставления и файл, и он распечатает вхождения в файле и номера строк, если хотите. Очень полезно и, вероятно, может быть связано с Python.

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