Документация Python неофициальный перевод
Содержание страницы

18.10. multifile – поддержка файлов, содержащих отдельные частиmultifile – Support for files containing distinct parts

Устарело с версии 2.5: Следует использовать пакет email вместо модуля multifile. Этот модуль присутствует только для сохранения обратной совместимости.

Объект MultiFile позволяет обрабатывать разделы текстового файла как файлоподобные объекты ввода, при этом '' возвращается readline() при обнаружении заданного шаблона-разделителя. Значения по умолчанию этого класса предназначены для использования при разборе MIME-сообщений с несколькими частями, но с помощью создания подкласса и переопределения методов его можно легко адаптировать для более общего использования.

class multifile.MultiFile(fp[, seekable])

Создаёт multi-file. Необходимо создать экземпляр этого класса с аргументом – объектом ввода, из которого экземпляр MultiFile будет получать строки, например, файловым объектом, возвращаемым open().

MultiFile всегда использует только методы readline(), seek() и tell() входного объекта, причём последние два нужны только для произвольного доступа к отдельным MIME-частям. Чтобы использовать MultiFile с непозиционируемым потоковым объектом, установите необязательный аргумент seekable в false; это предотвратит использование методов seek() и tell() входного объекта.

Полезно знать, что в представлении MultiFile текст состоит из трёх видов строк: данных, разделителей разделов и конечных маркеров. MultiFile предназначен для поддержки разбора сообщений, которые могут содержать несколько вложенных частей, каждая со своим шаблоном строк-разделителей и конечных маркеров.

См. также

Модуль email

Комплексный пакет для обработки электронной почты; заменяет модуль multifile.

18.10.1. Объекты MultiFileMultiFile Objects

Экземпляр MultiFile имеет следующие методы:

MultiFile.readline(str)

Читает строку. Если строка является данными (не разделителем раздела, не конечным маркером и не реальным концом файла), возвращает её. Если строка соответствует самой последней помещённой в стек границе, возвращает '' и устанавливает self.last в 1 или 0 в зависимости от того, является ли совпадение конечным маркером. Если строка соответствует любой другой границе из стека, вызывает исключение. При достижении конца файла в нижележащем потоковом объекте метод вызывает Error, если только все границы не были извлечены из стека.

MultiFile.readlines(str)

Возвращает все строки, оставшиеся в этой части, в виде списка строк.

MultiFile.read()

Читает все строки до следующего раздела. Возвращает их в виде одной (многострочной) строки. Обратите внимание: этот метод не принимает аргумент размера!

MultiFile.seek(pos[, whence])

Позиционирование. Индексы позиционирования задаются относительно начала текущего раздела. Аргументы pos и whence интерпретируются так же, как при позиционировании в файле.

MultiFile.tell()

Возвращает позицию в файле относительно начала текущего раздела.

MultiFile.next()

Пропускает строки до следующего раздела (то есть читает строки, пока не будет поглощён разделитель раздела или конечный маркер). Возвращает true, если такой раздел существует, и false, если обнаружен конечный маркер. Повторно активирует самую последнюю помещённую границу.

MultiFile.is_data(str)

Возвращает true, если str является данными, и false, если это может быть границей раздела. В текущей реализации проверяет, не начинается ли строка с префикса '--' (который есть у всех MIME-границ), но объявлена так, чтобы её можно было переопределить в производных классах.

Обратите внимание: эта проверка используется как быстрый предохранитель перед настоящими проверками границ; если она всегда возвращает false, это лишь замедлит обработку, но не приведёт к сбою.

MultiFile.push(str)

Помещает строку границы в стек. Когда во входной строке встречается оформленная версия этой границы, она интерпретируется как разделитель раздела или конечный маркер (в зависимости от оформления, см. RFC 2045). Все последующие чтения будут возвращать пустую строку, указывая на конец файла, пока вызов pop() не удалит границу, или вызов next() не активирует её повторно.

Можно поместить в стек несколько границ. Обнаружение самой последней помещённой границы вернёт EOF; обнаружение любой другой границы вызовет исключение.

MultiFile.pop()

Извлекает границу раздела из стека. Эта граница больше не будет интерпретироваться как EOF.

MultiFile.section_divider(str)

Преобразует границу в строку-разделитель раздела. По умолчанию этот метод добавляет в начало '--' (который есть у MIME-границ разделов), но объявлен так, чтобы его можно было переопределить в производных классах. Этот метод не должен добавлять LF или CR-LF, так как сравнение результата игнорирует завершающие пробельные символы.

MultiFile.end_marker(str)

Преобразует строку границы в строку конечного маркера. По умолчанию этот метод добавляет в начало '--' и в конец '--' (как маркер конца сообщения MIME-многокомпонентного сообщения), но объявлен так, чтобы его можно было переопределить в производных классах. Этот метод не должен добавлять LF или CR-LF, так как сравнение результата игнорирует завершающие пробельные символы.

Наконец, экземпляры MultiFile имеют две открытые переменные экземпляра:

MultiFile.level

Глубина вложенности текущей части.

MultiFile.last

True, если последний конец файла был маркером конца сообщения.

18.10.2. MultiFile ПримерMultiFile Example

import mimetools
import multifile
import StringIO

def extract_mime_part_matching(stream, mimetype):
    """Возвращает первый элемент многочастного MIME-сообщения в потоке
    соответствующий MIME-тип."""

    msg = mimetools.Message(stream)
    msgtype = msg.gettype()
    params = msg.getplist()

    data = StringIO.StringIO()
    if msgtype[:10] == "multipart/":

        file = multifile.MultiFile(stream)
        file.push(msg.getparam("boundary"))
        while file.next():
            submsg = mimetools.Message(file)
            try:
                data = StringIO.StringIO()
                mimetools.decode(file, data, submsg.getencoding())
            except ValueError:
                continue
            if submsg.gettype() == mimetype:
                break
        file.pop()
    return data.getvalue()