Содержание страницы
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 предназначен для поддержки разбора сообщений, которые могут содержать несколько вложенных частей, каждая со своим шаблоном строк-разделителей и конечных маркеров.
18.10.1. Объекты MultiFile¶MultiFile 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()