nntplib — Клиент протокола NNTP

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

Не рекомендуется, начиная с версии 3.11: Модуль nntplib является устаревшим (подробнее см. PEP 594).


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

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

>>> s = nntplib.NNTP('news.gmane.io')
>>> 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.io')
>>> 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. Если вы получаете неожиданные NNTPPermanentErrors, возможно, вам нужно установить readermode. Класс NNTP поддерживает оператор with для безусловного потребления исключений OSError и закрытия NNTP-соединения по завершении, например:

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

Вызывает auditing event nntplib.connect с аргументами self, host, port.

Вызывает auditing event nntplib.putline с аргументами self, line.

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

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

Изменено в версии 3.9: Если параметр timeout установлен равным нулю, то будет вызван сигнал ValueError для предотвращения создания неблокирующего сокета.

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-on-563 не рекомендуется использовать по RFC 4642, в пользу STARTTLS, как описано ниже. Однако некоторые серверы поддерживают только первый вариант.

Вызывает auditing event nntplib.connect с аргументами self, host, port.

Вызывает auditing event nntplib.putline с аргументами self, line.

Добавлено в версии 3.2.

Изменено в версии 3.4: Класс теперь поддерживает проверку имени хоста с помощью ssl.SSLContext.check_hostname и Server Name Indication (см. ssl.HAS_SNI).

Изменено в версии 3.9: Если параметр timeout установлен равным нулю, то будет вызван сигнал ValueError для предотвращения создания неблокирующего сокета.

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

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

Объекты NNTP

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

Атрибуты

NNTP.nntp_version

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

Добавлено в версии 3.2.

NNTP.nntp_implementation

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

Добавлено в версии 3.2.

Методы

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

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

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

NNTP.quit()

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

NNTP.getwelcome()

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

NNTP.getcapabilities()

Возвращает RFC 3977 возможности, рекламируемые сервером, в виде экземпляра dict, отображающего имена возможностей на (возможно, пустые) списки значений. На старых серверах, которые не понимают команду CAPABILITIES, вместо нее возвращается пустой словарь.

>>> s = NNTP('news.gmane.io')
>>> '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(context=None)

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

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

Добавлено в версии 3.2.

Изменено в версии 3.4: Метод теперь поддерживает проверку имени хоста с помощью ssl.SSLContext.check_hostname и Server Name Indication (см. ssl.HAS_SNI).

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

Отправьте команду NEWGROUPS. Аргумент date должен быть объектом datetime.date или datetime.datetime. Возвращает пару (response, groups), где groups - это список, представляющий группы, которые являются новыми с указанной даты. Если указан 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: Статьи от коллег вместо этого помещаются в группу «Хлам».

  • x: Нет локальных сообщений, а статьи от коллег игнорируются.

  • =foo.bar: Вместо этого статьи подаются в группу foo.bar.

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

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

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

NNTP.descriptions(grouppattern)

Отправьте команду LIST NEWSGROUPS, где grouppattern - это строка wildmat, указанная в RFC 3977 (по сути, это то же самое, что и строки wildcard оболочки 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), указывающим диапазон статей, начиная с первой до последней статьи в текущей группе, либо 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. Возвращаемые строки (или записываемые в файл) будут содержать только заголовки сообщения, а не тело.

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

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

NNTP.post(data)

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

Если метод работает успешно, возвращается ответ сервера. Если сервер отказывает в постинге, выдается сообщение NNTPReplyError.

NNTP.ihave(message_id, data)

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

NNTP.date()

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

NNTP.slave()

Отправьте команду SLAVE. Верните ответ сервера.

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 является file object, то он начнет вызывать write() на нем для хранения строк вывода команды. Если file предоставлен, то возвращаемый list будет пустым списком.

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

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

Функции полезности

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

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'
Вернуться на верх