Переход на Python для Mbox

#python #awk #mbox

#python #awk #mbox

Вопрос:

Какой был бы наилучший Pythonic способ реализации этой команды awk в python?

 awk 'BEGIN{chunk=0} /^From /{msgs  ;if(msgs==500){msgs=0;chunk  }}{print > "chunk_" chunk ".txt"}' mbox
  

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

Прямо сейчас я пробую рекурсивный метод.

 def chunkUp(mbox, chunk=0):
    with open(mbox, 'r') as bigfile:
        msg = 0
        for line in bigfile:
            if msg == 0: 
                with open("./TestChunks/chunks/chunk_" str(chunk) ".txt", "a ") as cf:
                    if line.startswith("From "): msg  = 1
                    cf.write(line)
                    if msg > 20: chunkUp(mbox, chunk 1)
  

Я хотел бы иметь возможность реализовать это на python и иметь возможность возобновить выполнение, если оно прервано. Сейчас работаю над этим.

Я завязываю свой мозг в узлы! Приветствую!

Комментарии:

1. рекурсивный — это плохо, потому что файлы не закрываются (слишком много открытых файлов через некоторое время)

2. хороший момент, я отойду от этого подхода.

Ответ №1:

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

Лучше открыть один дескриптор и записать в него, закрыть и повторно открыть новый дескриптор при обнаружении «From».

также открывайте свои файлы в режиме записи, а не добавления. Приведенный ниже код пытается выполнить минимальные операции и тесты для записи каждой строки в файл и закрыть / открыть другой файл, когда From: будет найден. Также, в конце, закрывается последний файл.

 def chunkUp(mbox):
    with open(mbox, 'r') as bigfile:
        handle = None
        chunk = 0

        for line in bigfile:
            if line.startswith("From "):
                 # next (or first) file
                 chunk  = 1
                 if handle is not None:
                    handle.close()
                 handle = None

            # file was closed / first file: create a new one
            if handle is None:
               handle = open("./TestChunks/chunks/chunk_{}.txt".format(chunk), "w")
            # write the line in the current file
            handle.write(line)

         if handle is not None:
             handle.close()
  

Я не тестировал это, но это достаточно просто, это должно сработать. Если в первой строке файла нет «From», все предыдущие строки сохраняются в chunk_0.txt файле.

Комментарии:

1. Я застрял при попытке использовать с open(). Это замечательное решение. Я буду реализовывать 500 сообщений на блок, как указано в команде awk, с помощью этого. Я отмечаю как отвеченный, поскольку он столкнулся с ментальным блоком обработки открытых файлов. Спасибо!