nntplib — NNTP 协议 Client 端

源代码: Lib/nntplib.py


该模块定义了实现网络新闻传输协议 Client 端的NNTP类。它可以用于实现新闻阅读器或海报,或自动新闻处理程序。它与 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对象,该对象表示与在主机* host 上运行的 NNTP 服务器的连接,侦听端口 port 。可以为套接字连接指定一个可选的 timeout 。如果提供了可选的 user password ,或者/.netrc中存在适当的凭据,并且可选标记 usenetrc 为 true,则AUTHINFO USERAUTHINFO PASS命令用于向服务器标识用户并对其进行身份验证。如果可选标志 readermode 为 true,则在执行身份验证之前发送mode reader命令。如果要连接到本地计算机上的 NNTP 服务器并打算调用特定于读取器的命令,例如group,则有时需要读取器模式。如果出现意外的NNTPPermanentError,则可能需要设置 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')
>>>

用参数selfhostport引发auditing event nntplib.connect

所有命令都将引发带有参数selflineauditing event nntplib.putline,其中line是将要发送到远程主机的字节。

在版本 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 * [,超时])
    • 返回一个新的NNTP_SSL对象,该对象表示与在主机* host 上运行的 NNTP 服务器的加密连接,侦听端口 port NNTP_SSL对象与NNTP对象具有相同的方法。如果Ellipsis port *,则使用端口 563(NNTPS)。 * ssl_context *也是可选的,并且是SSLContext对象。请阅读Security considerations了解最佳做法。所有其他参数的行为与NNTP相同。

请注意,每 RFC 4642不建议使用 SSL-on-563,而建议使用 STARTTLS,如下所述。但是,某些服务器仅支持前者。

用参数selfhostport引发auditing event nntplib.connect

所有命令都将引发带有参数selflineauditing event nntplib.putline,其中line是将要发送到远程主机的字节。

3.2 版中的新Function。

在版本 3.4 中进行了更改:该类现在支持使用ssl.SSLContext.check_hostname服务器名称指示(请参阅ssl.HAS_SNI)检查主机名。

  • exception nntplib. NNTPError

    • 从标准异常Exception派生,这是nntplib模块引发的所有异常的 Base Class。此类的实例具有以下属性:
  • response

    • 服务器的响应(如果可用),作为str对象。
  • exception nntplib. NNTPReplyError

    • 从服务器收到意外答复时引发的异常。
  • exception nntplib. NNTPTemporaryError

    • 收到 400-499 范围内的响应代码时引发异常。
  • exception nntplib. NNTPPermanentError

    • 收到 500-599 范围内的响应代码时引发异常。
  • exception nntplib. NNTPProtocolError

    • 从服务器收到的答复不是以 1 到 5 范围内的数字开头时引发的异常。
  • exception nntplib. NNTPDataError

    • 响应数据中存在某些错误时引发异常。

NNTP Objects

连接后,NNTPNNTP_SSL对象支持以下方法和属性。

Attributes

  • NNTP. nntp_version
    • 代表服务器支持的 NNTP 协议版本的整数。实际上,对于广告 RFC 3977合规性的服务器,该值为2;对于其他广告,则为1

3.2 版中的新Function。

  • NNTP. nntp_implementation
    • 一个字符串,描述 NNTP 服务器的软件名称和版本;如果服务器未发布,则为None

3.2 版中的新Function。

Methods

几乎所有方法的返回 Tuples 中作为第一项返回的* response *是服务器的响应:一个以三位数代码开头的字符串。如果服务器的响应指示错误,则该方法将引发上述异常之一。

以下许多方法采用可选的仅关键字参数* file 。提供 file *参数时,它必须是为二进制写入而打开的file object或要写入的磁盘文件的名称。然后,该方法会将服务器返回的所有数据(响应行和终止点除外)写入文件;该方法通常返回的任何行,Tuples 或对象列表将为空。

在 3.2 版中进行了更改:以下许多方法已被重新设计和修复,从而使其与 3.1 对应版本不兼容。

  • NNTP. quit ( )

    • 发送QUIT命令并关闭连接。调用此方法后,不应再调用 NNTP 对象的其他方法。
  • NNTP. getwelcome ( )

    • 返回服务器发送的欢迎消息以回复初始连接。 (此消息有时包含与用户相关的免责语句或帮助信息.)
  • NNTP. getcapabilities ( )

    • 返回服务器通告的 RFC 3977Function,作为dict实例将Function名称 Map 到(可能为空)值列表。在不了解CAPABILITIES命令的旧式服务器上,将返回一个空字典。
>>> s = NNTP('news.gmane.io')
>>> 'POST' in s.getcapabilities()
True

3.2 版中的新Function。

  • NNTP. login(* user = None password = None usenetrc = True *)
    • 使用用户名和密码发送AUTHINFO命令。如果* user password None usenetrc *为 true,则将尽可能使用~/.netrc的凭据。

除非有意地延迟,否则通常在NNTP对象初始化期间执行登录,并且不需要单独调用此函数。要强制延迟身份验证,创建对象时不得设置* user password ,并且必须将 usenetrc *设置为 False。

3.2 版中的新Function。

  • NNTP. starttls(* context = None *)

请注意,在发送了身份验证信息之后,可能无法完成此操作,并且如果可能的话,默认情况下会在NNTP对象初始化期间进行身份验证。有关抑制此行为的信息,请参见NNTP.login()

3.2 版中的新Function。

在版本 3.4 中进行了更改:该方法现在支持使用ssl.SSLContext.check_hostname服务器名称指示(请参阅ssl.HAS_SNI)进行主机名检查。

  • NNTP. newgroups(* date **,* file = None *)
    • 发送NEWGROUPS命令。 * date 参数应为datetime.datedatetime.datetime对象。返回Pair(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()相同的含义。返回Pair(response, articles),其中 articles *是消息 ID 的列表。

NNTP 服务器 Management 员经常禁用此命令。

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

    • 发送LISTLIST ACTIVE命令。返回Pair(response, list),其中* list 是表示该 NNTP 服务器可用的所有组的 Tuples 列表,可以选择匹配模式字符串 group_pattern 。每个 Tuples 的格式为(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 RFC 3977中指定的通配符字符串(与 DOS 或 UNIX shell 通配符字符串基本相同)。返回Pair(response, descriptions),其中 descriptions *是将组名 Map 到文本描述的字典。
>>> 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 是组名。该组被选择为当前组(如果存在)。返回一个 Tuples(response, count, first, last, name),其中 count 是组中商品的(估计)数量, first 是组中的第一个商品编号, last 是组中的最后一个商品编号, name *是组中的最后一个商品编号团队名字。
  • NNTP. over(* message_spec **,* file = None *)

    • 在旧版服务器上发送OVER命令或XOVER命令。 * message_spec 可以是表示消息 ID 的字符串,也可以是表示当前组中文章范围的(first, last)数字 Tuples,也可以是表示从当前的第一*到最后一篇文章的范围的(first, None)Tuples 组,或None选择当前组中的当前文章。

返回Pair(response, overviews)。 * overviews (article_number, overview)个 Tuples 的列表,每个列表由 message_spec *选择。每个“概述”都是具有相同数量项的字典,但是此数量取决于服务器。这些项目是消息 Headers(该键为小写 Headers 名称)或元数据项目(该键为以":"开头的元数据名称)。 NNTP 规范保证存在以下各项:

  • subjectfromdatemessage-idreferencesHeaders

  • :bytes元数据:整个原始文章中的字节数(包括标题和正文)

  • :lines元数据:文章正文中的行数

每个项目的值可以是一个字符串,如果不存在则为None

当 Headers 值可能包含非 ASCII 字符时,建议对它们使用decode_header()函数:

>>> _, _, 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?= <[email protected]>'
>>> nntplib.decode_header(over['from'])
'"Martin v. Löwis" <[email protected]>'

3.2 版中的新Function。

  • NNTP. help(** file = None *)

    • 发送HELP命令。返回Pair(response, list),其中* list *是帮助字符串的列表。
  • NNTP. stat(* message_spec = None *)

    • 发送STAT命令,其中* message_spec 是消息 ID(用'<''>'括起来)或当前组中的商品编号。如果Ellipsis message_spec None,则考虑当前组中的当前文章。返回三 Tuples(response, number, id),其中 number 是商品编号, id *是消息 ID。
>>> _, _, first, last, _ = s.group('gmane.comp.python.devel')
>>> resp, number, message_id = s.stat(first)
>>> number, message_id
(9099, '<[email protected]>')
  • NNTP. next ( )

    • 发送NEXT命令。返回stat()
  • NNTP. last ( )

    • 发送LAST命令。返回stat()
  • NNTP. article(* message_spec = None **,* file = None *)

    • 发送ARTICLE命令,其中* message_spec stat()具有相同的含义。返回 Tuples(response, info),其中 info namedtuple,具有三个属性 number message_id lines *(按此 Sequences)。 * number 是组中的商品编号(如果信息不可用,则为 0), message_id 消息 ID 为字符串, lines *包含原始消息(包括标题)的行列表(不包含换行符)和身体。
>>> resp, info = s.article('<[email protected]>')
>>> info.number
0
>>> info.message_id
'<[email protected]>'
>>> len(info.lines)
65
>>> info.lines[0]
b'Path: main.gmane.org!not-for-mail'
>>> info.lines[1]
b'From: Neal Norwitz <[email protected]>'
>>> 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 *)将仅包含消息正文,而不包含 Headers。
  • NNTP. post(* data *)

    • 使用POST命令发布文章。 * data *参数是为二进制读取而打开的file object,或者是任何可迭代的字节对象(表示要发布的文章的原始行)。它应该代表格式良好的新闻文章,包括必需的标题。 post()方法自动转义以.开头的行,并附加终止行。

如果该方法成功,则返回服务器的响应。如果服务器拒绝发布,则会引发NNTPReplyError

  • NNTP. ihave(* message_id data *)

    • 发送IHAVE命令。 * message_id *是要发送到服务器的消息的 ID(用'<''>'括起来)。 * data *参数和返回值与post()相同。
  • NNTP. date ( )

    • 返回Pair(response, date)。 * date *是一个datetime对象,其中包含服务器的当前日期和时间。
  • NNTP. slave ( )

    • 发送SLAVE命令。返回服务器的* response *。
  • NNTP. set_debuglevel(级别)

    • 设置实例的调试级别。这控制打印的调试输出的数量。默认值0不产生调试输出。值1产生适度的调试输出,通常每个请求或响应一行。 2或更高的值将产生最大的调试输出量,记录连接上发送和接收的每一行(包括消息文本)。

以下是 RFC 2980中定义的可选 NNTP 扩展。其中一些已被 RFC 3977中的更新命令所取代。

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

    • 发送XHDR命令。 * hdr *参数是标题关键字,例如'subject'。 * str 参数的格式应为'first-last',其中 first last 是要搜索的第一和最后一个商品编号。返回对(response, list),其中 list 是对(id, text)的列表,其中 id 是商品编号(作为字符串),而 text 是该商品的请求 Headers 的文本。如果提供了 file 参数,则XHDR命令的输出存储在文件中。如果 file 是字符串,则该方法将打开具有该名称的文件,写入该文件,然后将其关闭。如果 file file object,它将开始在其上调用write()来存储命令输出的行。如果提供了 file ,则返回的 list *是一个空列表。
  • NNTP. xover(* start end **,* file = None *)

    • 发送XOVER命令。 开始结束是物品编号,界定了要选择的物品范围。返回值与over()相同。建议改用over(),因为它会自动使用更新的OVER命令(如果有)。
  • NNTP. xpath(* id *)

    • 返回Pair(resp, path),其中* path *是带有消息 ID * id *的文章的目录路径。大多数情况下,NNTP 服务器 Management 员未启用此扩展。

从版本 3.3 开始不推荐使用:XPATH 扩展未积极使用。

Utility functions

该模块还定义了以下 Util Function:

  • nntplib. decode_header(* header_str *)
    • 解码 Headers 值,对所有转义的非 ASCII 字符进行转义。 * header_str *必须是str对象。返回未转义的值。建议使用此Function以易于阅读的形式显示一些标题:
>>> 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'