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

21.16. nntplib – клиент протокола NNTPnntplib – NNTP protocol client

Исходный код: Lib/nntplib.py


Этот модуль определяет класс NNTP, который реализует клиентскую часть протокола передачи сетевых новостей (Network News Transfer Protocol). Его можно использовать для создания программы чтения новостей, отправки новостей или автоматизированной обработки новостей. Он совместим с RFC 3977, а также с более старыми RFC 977 и RFC 2980.

Вот два небольших примера использования. Чтобы вывести статистику по группе новостей и напечатать темы последних 10 статей:

>>> s = nntplib.NNTP('news.gmane.org')
>>> resp, count, first, last, name = s.group('gmane.comp.python.committers')
>>> print('Group', name, 'has', count, 'articles, range', first, 'to', last)
Group gmane.comp.python.committers has 1096 articles, range 1 to 1096
>>> resp, overviews = s.over((last - 9, last))
>>> for id, over in overviews:
...     print(id, nntplib.decode_header(over['subject']))
...
1087 Re: Commit privileges for Łukasz Langa
1088 Re: 3.2 alpha 2 freeze
1089 Re: 3.2 alpha 2 freeze
1090 Re: Commit privileges for Łukasz Langa
1091 Re: Commit privileges for Łukasz Langa
1092 Updated ssh key
1093 Re: Updated ssh key
1094 Re: Updated ssh key
1095 Hello fellow committers!
1096 Re: Hello fellow committers!
>>> s.quit()
'205 Bye!'

Чтобы опубликовать статью из двоичного файла (предполагается, что статья содержит корректные заголовки и у вас есть права на публикацию в данной группе новостей):

>>> s = nntplib.NNTP('news.gmane.org')
>>> f = open('article.txt', 'rb')
>>> s.post(f)
'240 Article posted successfully.'
>>> s.quit()
'205 Bye!'

Сам модуль определяет следующие классы:

class nntplib.NNTP(host, port=119, user=None, password=None, readermode=None, usenetrc=False[, timeout])

Возвращает новый объект NNTP, представляющий соединение с NNTP-сервером, работающим на узле host, прослушивающим порт port. Для сокетного соединения можно указать необязательный timeout. Если указаны необязательные user и password, или если подходящие учётные данные присутствуют в /.netrc и необязательный флаг usenetrc равен true, для идентификации и аутентификации пользователя на сервере используются команды AUTHINFO USER и AUTHINFO PASS. Если необязательный флаг readermode равен true, то перед выполнением аутентификации отправляется команда mode reader. Режим читателя иногда необходим, если вы подключаетесь к NNTP-серверу на локальной машине и собираетесь вызывать специфичные для читателя команды, такие как group. Если вы получаете неожиданные NNTPPermanentError, возможно, потребуется установить readermode. Класс NNTP поддерживает оператор with для безусловного перехвата исключений socket.error и закрытия NNTP-соединения по завершении. Ниже приведён пример использования:

>>> from nntplib import NNTP
>>> with NNTP('news.gmane.org') as n:
...     n.group('gmane.comp.python.committers')
...
('211 1755 1 1755 gmane.comp.python.committers', 1755, 1, 1755, 'gmane.comp.python.committers')
>>>

Изменено в версии 3.2: usenetrc теперь по умолчанию False.

Изменено в версии 3.3: Добавлена поддержка оператора with.

class nntplib.NNTP_SSL(host, port=563, user=None, password=None, ssl_context=None, readermode=None, usenetrc=False[, timeout])

Возвращает новый объект NNTP_SSL, представляющий зашифрованное соединение с NNTP-сервером, работающим на узле host, прослушивающим порт port. Объекты NNTP_SSL имеют те же методы, что и объекты NNTP. Если port опущен, используется порт 563 (NNTPS). ssl_context также необязателен и представляет собой объект SSLContext. Все остальные параметры ведут себя так же, как для NNTP.

Обратите внимание, что SSL на порту 563 не рекомендуется согласно RFC 4642, вместо него следует использовать STARTTLS, как описано ниже. Однако некоторые серверы поддерживают только первый вариант.

Новое в версии 3.2.

exception nntplib.NNTPError

Производный от стандартного исключения Exception, это базовый класс для всех исключений, возбуждаемых модулем nntplib. Экземпляры этого класса имеют следующий атрибут:

response

Ответ сервера, если доступен, в виде объекта str.

exception nntplib.NNTPReplyError

Исключение, возникающее при получении неожиданного ответа от сервера.

exception nntplib.NNTPTemporaryError

Исключение возбуждается, когда получен код ответа в диапазоне 400–499.

exception nntplib.NNTPPermanentError

Исключение возбуждается, когда получен код ответа в диапазоне 500–599.

exception nntplib.NNTPProtocolError

Исключение возбуждается, когда от сервера получен ответ, который не начинается с цифры в диапазоне 1–5.

exception nntplib.NNTPDataError

Исключение возбуждается при наличии ошибки в данных ответа.

21.16.1. Объекты NNTPNNTP Objects

При подключении объекты NNTP и NNTP_SSL поддерживают следующие методы и атрибуты.

21.16.1.1. АтрибутыAttributes

NNTP.nntp_version

Целое число, представляющее версию протокола NNTP, поддерживаемую сервером. На практике должно быть равно 2 для серверов, заявляющих о соответствии RFC 3977, и 1 для остальных.

Новое в версии 3.2.

NNTP.nntp_implementation

Строка, описывающая название программного обеспечения и версию сервера NNTP, или None, если сервер не сообщил эту информацию.

Новое в версии 3.2.

21.16.1.2. МетодыMethods

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

Многие из следующих методов принимают необязательный аргумент, передаваемый только по ключу, file. Когда аргумент file указан, он должен быть либо файловый объект, открытым для бинарной записи, либо именем файла на диске для записи. В этом случае метод будет записывать все данные, возвращаемые сервером (за исключением строки ответа и завершающей точки), в файл; любой список строк, кортежей или объектов, который метод обычно возвращает, будет пуст.

Изменено в версии 3.2: Многие из следующих методов были переработаны и исправлены, что делает их несовместимыми с их аналогами из версии 3.1.

NNTP.quit()

Отправляет команду QUIT и закрывает соединение. После вызова этого метода не следует вызывать другие методы объекта NNTP.

NNTP.getwelcome()

Возвращает приветственное сообщение, отправленное сервером в ответ на начальное подключение. (Это сообщение иногда содержит отказ от ответственности или справочную информацию, которая может быть полезна пользователю.)

NNTP.getcapabilities()

Return the RFC 3977 capabilities advertised by the server, as a dict instance mapping capability names to (possibly empty) lists of values. On legacy servers which don’t understand the CAPABILITIES command, an empty dictionary is returned instead.

>>> s = NNTP('news.gmane.org')
>>> 'POST' in s.getcapabilities()
True

Новое в версии 3.2.

NNTP.login(user=None, password=None, usenetrc=True)

Отправляет команды AUTHINFO с именем пользователя и паролем. Если user и password равны None, а usenetrc равен true, то по возможности будут использованы учётные данные из ~/.netrc.

Если намеренно не отложено, вход обычно выполняется во время инициализации объекта NNTP, и отдельный вызов этой функции не требуется. Чтобы отложить аутентификацию, не указывайте user или password при создании объекта и установите usenetrc в False.

Новое в версии 3.2.

NNTP.starttls(ssl_context=None)

Отправляет команду STARTTLS. Аргумент ssl_context необязателен и должен быть объектом ssl.SSLContext. Это включит шифрование в NNTP-соединении.

Обратите внимание, что это нельзя делать после передачи аутентификационных данных; аутентификация по умолчанию выполняется, если это возможно, во время инициализации объекта NNTP. См. NNTP.login() для получения информации о том, как подавить это поведение.

Новое в версии 3.2.

NNTP.newgroups(date, *, file=None)

Отправляет команду NEWGROUPS. Аргумент date должен быть объектом datetime.date или datetime.datetime. Возвращает пару (response, groups), где groups – это список, представляющий группы, появившиеся после указанной даты date. Однако если указан file, то groups будет пустым.

>>> from datetime import date, timedelta
>>> resp, groups = s.newgroups(date.today() - timedelta(days=3))
>>> len(groups)
85
>>> groups[0]
GroupInfo(group='gmane.network.tor.devel', last='4', first='1', flag='m')
NNTP.newnews(group, date, *, file=None)

Отправляет команду NEWNEWS. Здесь group – это имя группы или '*', а date имеет то же значение, что и для newgroups(). Возвращает пару (response, articles), где articles – это список идентификаторов сообщений.

Эта команда часто отключается администраторами NNTP-серверов.

NNTP.list(group_pattern=None, *, file=None)

Отправляет команду LIST или LIST ACTIVE. Возвращает пару (response, list), где list – это список кортежей, представляющих все группы, доступные на этом сервере NNTP, при необходимости соответствующие строке шаблона group_pattern. Каждый кортеж имеет вид (group, last, first, flag), где group – имя группы, last и first – номера последнего и первого сообщений, а flag обычно принимает одно из следующих значений:

  • y: разрешены локальные публикации и сообщения от других серверов.
  • m: группа модерируется, и все публикации должны быть одобрены.
  • n: локальные публикации запрещены, разрешены только сообщения от других серверов.
  • j: сообщения от других серверов вместо этого помещаются в группу junk.
  • x: локальные публикации запрещены, а сообщения от других серверов игнорируются.
  • =foo.bar: сообщения вместо этого помещаются в группу foo.bar.

Если flag имеет другое значение, статус группы новостей следует считать неизвестным.

Эта команда может возвращать очень большие результаты, особенно если group_pattern не указан. Результаты лучше кэшировать в автономном режиме, если только нет реальной необходимости их обновлять.

Изменено в версии 3.2: был добавлен group_pattern.

NNTP.descriptions(grouppattern)

Отправляет команду LIST NEWSGROUPS, где grouppattern – это строка wildmat, как указано в RFC 3977 (она по сути аналогична строкам шаблонов DOS или UNIX). Возвращает пару (response, descriptions), где descriptions – это словарь, сопоставляющий имена групп с текстовыми описаниями.

>>> resp, descs = s.descriptions('gmane.comp.python.*')
>>> len(descs)
295
>>> descs.popitem()
('gmane.comp.python.bio.general', 'BioPython discussion list (Moderated)')
NNTP.description(group)

Получает описание для одной группы group. Если совпадает несколько групп (если ‘group’ – это строка шаблона wildmat), возвращается первое совпадение. Если ни одна группа не совпадает, возвращается пустая строка.

Этот метод опускает код ответа сервера. Если код ответа нужен, используйте descriptions().

NNTP.group(name)

Отправляет команду GROUP, где name – имя группы. Группа выбирается в качестве текущей, если она существует. Возвращает кортеж (response, count, first, last, name), где count – (приблизительное) количество сообщений в группе, first – номер первого сообщения, last – номер последнего сообщения, а name – имя группы.

NNTP.over(message_spec, *, file=None)

Отправляет команду OVER или команду XOVER на устаревших серверах. message_spec может быть либо строкой, представляющей идентификатор сообщения, либо кортежем (first, last) чисел, указывающим диапазон статей в текущей группе, либо кортежем (first, None), указывающим диапазон статей от first до последней статьи в текущей группе, или None для выбора текущей статьи в текущей группе.

Возвращает пару (response, overviews). overviews – это список кортежей (article_number, overview), по одному на каждое сообщение, выбранное message_spec. Каждый overview – это словарь с одинаковым количеством элементов, но это количество зависит от сервера. Эти элементы могут быть либо заголовками сообщения (тогда ключ – имя заголовка в нижнем регистре), либо элементами метаданных (тогда ключ – имя метаданных с префиксом ":"). Следующие элементы гарантированно присутствуют согласно спецификации NNTP:

  • заголовки subject, from, date, message-id и references
  • метаданные :bytes: количество байтов во всём необработанном сообщении (включая заголовки и тело)
  • метаданные :lines: количество строк в теле сообщения

Значение каждого элемента – строка или None, если он отсутствует.

Рекомендуется использовать функцию decode_header() для значений заголовков, которые могут содержать не-ASCII символы:

>>> _, _, first, last, _ = s.group('gmane.comp.python.devel')
>>> resp, overviews = s.over((last, last))
>>> art_num, over = overviews[0]
>>> art_num
117216
>>> list(over.keys())
['xref', 'from', ':lines', ':bytes', 'references', 'date', 'message-id', 'subject']
>>> over['from']
'=?UTF-8?B?Ik1hcnRpbiB2LiBMw7Z3aXMi?= <martin@v.loewis.de>'
>>> nntplib.decode_header(over['from'])
'"Martin v. Löwis" <martin@v.loewis.de>'

Новое в версии 3.2.

NNTP.help(*, file=None)

Отправляет команду HELP. Возвращает пару (response, list), где list – это список строк справки.

NNTP.stat(message_spec=None)

Отправляет команду STAT, где message_spec – это либо идентификатор сообщения (заключённый в '<' и '>'), либо номер сообщения в текущей группе. Если message_spec опущен или равен None, рассматривается текущее сообщение в текущей группе. Возвращает тройку (response, number, id), где number – номер сообщения, а id – идентификатор сообщения.

>>> _, _, first, last, _ = s.group('gmane.comp.python.devel')
>>> resp, number, message_id = s.stat(first)
>>> number, message_id
(9099, '<20030112190404.GE29873@epoch.metaslash.com>')
NNTP.next()

Отправляет команду NEXT. Возвращаемое значение – как у stat().

NNTP.last()

Отправляет команду LAST. Возвращаемое значение – как у stat().

NNTP.article(message_spec=None, *, file=None)

Отправляет команду ARTICLE, где message_spec имеет то же значение, что и для stat(). Возвращает кортеж (response, info), где info – это namedtuple с тремя атрибутами number, message_id и lines (в указанном порядке). number – номер статьи в группе (или 0, если информация недоступна), message_id – идентификатор сообщения в виде строки, а lines – список строк (без завершающих символов новой строки), составляющих исходное сообщение, включая заголовки и тело.

>>> resp, info = s.article('<20030112190404.GE29873@epoch.metaslash.com>')
>>> info.number
0
>>> info.message_id
'<20030112190404.GE29873@epoch.metaslash.com>'
>>> len(info.lines)
65
>>> info.lines[0]
b'Path: main.gmane.org!not-for-mail'
>>> info.lines[1]
b'From: Neal Norwitz <neal@metaslash.com>'
>>> info.lines[-3:]
[b'There is a patch for 2.3 as well as 2.2.', b'', b'Neal']
NNTP.head(message_spec=None, *, file=None)

То же, что и article(), но отправляет команду HEAD. Возвращаемые lines (или записанные в file) будут содержать только заголовки сообщения, но не тело.

NNTP.body(message_spec=None, *, file=None)

То же, что и article(), но отправляет команду BODY. Возвращаемые lines (или записанные в file) будут содержать только тело сообщения, а не заголовки.

NNTP.post(data)

Отправляет статью с помощью команды POST. Аргумент data может быть либо файловым объектом, открытым для двоичного чтения, либо любым итерируемым объектом из байтовых строк (представляющих исходные строки публикуемой статьи). Он должен представлять правильно оформленную новостную статью, включая необходимые заголовки. Метод post() автоматически экранирует строки, начинающиеся с ., и добавляет завершающую строку.

В случае успеха возвращается ответ сервера. Если сервер отказывается принимать публикацию, возбуждается NNTPReplyError.

NNTP.ihave(message_id, data)

Отправляет команду IHAVE. message_id – это идентификатор сообщения для отправки серверу (заключённый в '<' и '>'). Параметр data и возвращаемое значение такие же, как для post().

NNTP.date()

Возвращает пару (response, date). date – это объект datetime, содержащий текущие дату и время сервера.

NNTP.slave()

Отправляет команду SLAVE. Возвращает response сервера.

NNTP.set_debuglevel(level)

Устанавливает уровень отладки экземпляра. Он управляет объёмом выводимых отладочных сообщений. Значение по умолчанию, 0, не выводит отладочные сообщения. Значение 1 выдаёт умеренное количество отладочной информации, обычно одну строку на запрос или ответ. Значение 2 или больше выводит максимальный объём отладочной информации, регистрируя каждую отправленную и полученную строку соединения (включая текст сообщения).

Ниже перечислены необязательные расширения NNTP, определённые в RFC 2980. Некоторые из них заменены более новыми командами в RFC 3977.

NNTP.xhdr(hdr, str, *, file=None)

Отправляет команду XHDR. Аргумент hdr – это ключевое слово заголовка, например, 'subject'. Аргумент str должен иметь вид 'first-last', где first и last – первый и последний номера статей для поиска. Возвращает пару (response, list), где list – это список пар (id, text); id – номер статьи (в виде строки), а text – текст запрошенного заголовка для этой статьи. Если указан параметр file, выходные данные команды XHDR сохраняются в файл. Если file – строка, метод откроет файл с таким именем, запишет в него данные и закроет его. Если file – это файловый объект, он будет вызывать write() для него, чтобы сохранить строки выходных данных команды. Если file указан, то возвращаемый list будет пустым списком.

NNTP.xover(start, end, *, file=None)

Отправляет команду XOVER. start и end – это номера статей, определяющие диапазон статей для выбора. Возвращаемое значение такое же, как для over(). Рекомендуется использовать over(), так как он автоматически применит более новую команду OVER, если она доступна.

NNTP.xpath(id)

Возвращает пару (resp, path), где path – это путь к каталогу статьи с идентификатором сообщения id. В большинстве случаев это расширение не включено администраторами серверов NNTP.

Устарело с версии 3.3: Расширение XPATH активно не используется.

21.16.2. Вспомогательные функцииUtility functions

Модуль также определяет следующую вспомогательную функцию:

nntplib.decode_header(header_str)

Декодирует значение заголовка, снимая экранирование любых экранированных не-ASCII символов. header_str должен быть объектом str. Возвращается нераскодированное значение. Эту функцию рекомендуется использовать для отображения некоторых заголовков в удобочитаемой форме:

>>> decode_header("Some subject")
'Some subject'
>>> decode_header("=?ISO-8859-15?Q?D=E9buter_en_Python?=")
'Débuter en Python'
>>> decode_header("Re: =?UTF-8?B?cHJvYmzDqG1lIGRlIG1hdHJpY2U=?=")
'Re: problème de matrice'