KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Роман Сузи - Язык программирования Python

Роман Сузи - Язык программирования Python

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Роман Сузи, "Язык программирования Python" бесплатно, без регистрации.
Перейти на страницу:

• Модули для работы с форматами данных обычно содержат функции или конструкторы классов, в частности Reader и Writer.

• Эти функции и конструкторы возвращают объекты–итераторы для чтения данных из файла и объекты со специальными методами для записи в файл.

• Для разных нужд обычно требуется иметь несколько вариантов классов читающих и пишущих объектов. Новые классы могут получаться наследованием от базовых классов либо обертыванием функций, предоставляемых модулем расширения (написанным на C). В приведенном примере DictReader и DictWriter являются обертками для функций reader() и writer() и объектов, которые они порождают.

Пакет email

Модули пакета email помогут разобрать, изменить и сгенерировать сообщение в формате RFC 2822. Наиболее часто RFC 2822 применяется в сообщениях электронной почты в Интернете.

В пакете есть несколько модулей, назначение которых (кратко) указано ниже:

Message

Модуль определяет класс Message — основной класс для представления сообщения в пакете email.

Parser

Модуль для разбора представленного в виде текста сообщения с получением объектной структуры сообщения.

Header

Модуль для работы с полями, в которых используется кодировка, отличная от ASCII.

Generator

Порождает текст сообщения RFC 2822 на основании объектной модели.

Utils

Различные утилиты, которые решают разнообразные небольшие задачи, связанные с сообщениями.

В пакете есть и другие модули, которые здесь рассматриваться не будут.

Разбор сообщения. Класс Message

Класс Message — центральный во всем пакете email. Он определяет методы для работы с сообщением, которое состоит из заголовка (header) и тела (payload). Поле заголовка имеет название и значение, разделенное двоеточием (двоеточие не входит ни в название, ни в значение). Названия полей нечувствительны к регистру букв при поиске значения, хотя хранятся с учетом регистра. В классе также определены методы для доступа к некоторым часто используемым сведениям (кодировке сообщения, типу содержимого и т.п.).

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

Пример наиболее употребительных методов экземпляров класса Message с пояснениями:

>>> import email

>>> input_file = open("pr1.eml")

>>> msg = email.message_from_file(input_file)

Здесь используется функция email.message_from_file() для чтения сообщения из файла pr1.eml. Сообщение можно получить и из строки с помощью функции email.message_from_string(). А теперь следует произвести некоторые операции над этим сообщением (не стоит обращать внимания на странные имена — сообщение было взято из папки СПАМ). Доступ к полям по имени осуществляется так:

>>> print msg['from']

"felton olive" < [email protected]>

>>> msg.get_all('received')

['from mail.onego.runtby localhost with POP3 (fetchmail–6.2.5

polling mail.onego.ru account spam)ntfor [email protected]

(single–drop); Wed, 01 Sep 2004 15:46:33 +0400 (MSD)',

'from thecanadianteacher.com ([222.65.104.100])ntby mail.onego.ru

(8.12.11/8.12.11) with SMTP id i817UtUN026093;ntWed, 1 Sep 2004

11:30:58 +0400']

Стоит заметить, что в электронном письме может быть несколько полей с именем received (в этом примере их два).

Некоторые важные данные можно получить в готовом виде, например, тип содержимого, кодировку:

>>> msg.get_content_type()

'text/plain'

>>> print msg.get_main_type(), msg.get_subtype()

text plain

>>> print msg.get_charset()

None

>>> print msg.get_params()

[('text/plain', ''), ('charset', 'us–ascii')]

>>> msg.is_multipart()

False

или список полей:

>>> print msg.keys()

['Received', 'Received', 'Message–ID', 'Date', 'From', 'User–Agent',

'MIME–Version', 'To', 'Subject', 'Content–Type',

'Content–Transfer–Encoding', 'Spam', 'X–Spam']

Так как сообщение состоит из одной части, можно получить его тело в виде строки:

>>> print msg.get_payload()

sorgeloosheid hullw ifesh nozama decompresssequenceframes


Believe it or not, I have tried several sites to b»_«uy presription

medication. I should say that currently you are still be the best amony

...

Теперь будет рассмотрен другой пример, в котором сообщение состоит из нескольких частей. Это сообщение порождено вирусом. Оно состоит из двух частей: HTML–текста и вложенного файла с расширением cpl. Для доступа к частям сообщения используется метод walk(), который обходит все его части. Попутно следует собрать типы содержимого (в списке parts), поля Content–Type (в ct_fields) и имена файлов (в filenames):

import email

parts = []

ct_fields = []

filenames = []

f = open("virus.eml")

msg = email.message_from_file(f)

for submsg in msg.walk():

 parts.append(submsg.get_content_type())

 ct_fields.append(submsg.get('Content–Type', ''))

 filenames.append(submsg.get_filename())

 if submsg.get_filename():

  print "Длина файла:", len(submsg.get_payload())

f.close()

print parts

print ct_fields

print filenames

В результате получилось:

Длина файла: 31173

['multipart/mixed', 'text/html', 'application/octet–stream']

['multipart/mixed;n boundary="--------hidejpxkblmvuwfplzue"',

'text/html; charset="us–ascii"',

'application/octet–stream; name="price.cpl"']

[None, None, 'price.cpl']

Из списка parts можно увидеть, что само сообщение имеет тип multipart/mixed, тогда как две его части — text/html и application/octet–stream соответственно. Только с последней частью связано имя файла (price.cpl). Файл читается методом get_payload() и вычисляется его длина.

Кстати, в случае, когда сообщение является контейнером для других частей, get_payload() выдает список объектов–сообщений (то есть экземпляров класса Message).

Формирование сообщения

Часто возникает ситуация, когда нужно сформировать сообщение с вложенным файлом. В следующем примере строится сообщение с текстом и вложением. В качестве класса для порождения сообщения можно использовать не только Message из модуля email.Message, но и MIMEMultipart из email.MIMEMultipart (для сообщений из нескольких частей), MIMEImage (для сообщения с графическим изображением), MIMEAudio (для аудиофайлов), MIMEText (для текстовых частей):

# Загружаются необходимые модули и функции из модулей

from email.Header import make_header as mkh

from email.MIMEMultipart import MIMEMultipart

from email.MIMEText import MIMEText

from email.MIMEBase import MIMEBase

from email.Encoders import encode_base64


# Создается главное сообщение и задаются некоторые поля

msg = MIMEMultipart()

msg["Subject"] = mkh([("Привет", "koi8–r")])

msg["From"] = mkh([("Друг", "koi8–r"), ("< [email protected]>", "us–ascii")])

msg["To"] = mkh([("Друг2", "koi8–r"), ("< [email protected]>", "us–ascii")])


# То, чего будет не видно, если почтовая программа поддерживает MIME

msg.preamble = "Multipart message"

msg.epilogue = ""


# Текстовая часть сообщения

text = u"""К письму приложен файл с архивом.""".encode("koi8–r")

to_attach = MIMEText(text, _charset="koi8–r")

msg.attach(to_attach)


# Прикладывается файл

fp = open("archive_file.zip", "rb")

to_attach = MIMEBase("application", "octet–stream")

to_attach.set_payload(fp.read())

encode_base64(to_attach)

to_attach.add_header("Content–Disposition", "attachment",

 filename="archive_file.zip")

fp.close()

msg.attach(to_attach)


print msg.as_string()

В этом примере видно сразу несколько модулей пакета email. Функция make_header() из email.Header позволяет закодировать содержимое для заголовка:

>>> from email.Header import make_header

>>> print make_header([("Друг", "koi8–r"), ("< [email protected]>", "us–ascii")])

=?koi8–r?b?5NLVxw==?= < [email protected]>

>>> print make_header([(u"Друг", ""), ("< [email protected]>", "us–ascii")])

=?utf–8?b?w6TDksOVw4c=?= < [email protected]>

Функция email.Encoders.encode_base64() воздействует на переданное ей сообщение и кодирует тело с помощью base64. Другие варианты: encode_quopri() — кодировать quoted printable, encode_7or8bit() — оставить семь или восемь бит. Эти функции добавляют необходимые поля.

Аргументы конструкторов классов из MIME–модулей пакета email:

class MIMEBase(_maintype, _subtype, **_params)

Базовый класс для всех использующих MIME сообщений (подклассов Message). Тип содержимого задается через _maintype и _subtype.

class MIMENonMultipart()

Подкласс для MIMEBase, в котором запрещен метод attach(), отчего он гарантированно состоит из одной части.

class MIMEMultipart([_subtype[, boundary[, _subparts[, _params]]]])

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*