nntplib
--- NNTP 协议客户端¶
源代码: Lib/nntplib.py
此模块定义了 NNTP
类来实现网络新闻传输协议的客户端。 它可被用于实现一个新闻阅读或发布器,或是新闻自动处理程序。 它兼容了 RFC 3977 以及较旧的 RFC 977 和 RFC 2980。
Availability: not Emscripten, not WASI.
This module does not work or is not available on WebAssembly platforms
wasm32-emscripten
and wasm32-wasi
. See
WebAssembly platforms for more information.
下面是此模块的两个简单用法示例。 列出某个新闻组的一些统计数据并打印最近 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,在端口 port 上监听的 NNTP 服务器的连接。 可以为套接字连接指定可选的 timeout。 如果提供了可选的 user 和 password,或者如果在/.netrc
中存在适合的凭证并且可选的旗标 usenetrc 为真值,则会使用AUTHINFO USER
和AUTHINFO PASS
命令在服务器上标识和认证用户。 如果可选的旗标 readermode 为真值,则会在执行认证之前发送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') >>>
引发一个 审计事件
nntplib.connect
,附带参数self
,host
,port
。引发一个 审计事件
nntplib.putline
,附带参数self
,line
。在 3.2 版本发生变更: usenetrc 现在默认为
False
。在 3.3 版本发生变更: 添加了对
with
语句的支持。在 3.9 版本发生变更: 如果 timeout 参数设置为 0,创建非阻塞套接字时,它将引发
ValueError
来阻止该操作。
- class nntplib.NNTP_SSL(host, port=563, user=None, password=None, ssl_context=None, readermode=None, usenetrc=False[, timeout])¶
返回一个新的
NNTP_SSL
对象,代表一个对运行于主机 host,在端口 port 上监听的 NNTP 服务器的连接。NNTP_SSL
对象具有与NNTP
对象相同的方法。 如果 port 被省略,则会使用端口 563 (NNTPS)。 ssl_context 也是可选的,且为一个SSLContext
对象。 请阅读 安全考量 来了解最佳实践。 所有其他形参的行为都与NNTP
的相同。请注意 RFC 4642 不再推荐使用 563 端口的 SSL,建议改用下文描述的 STARTTLS。 但是,某些服务器只支持前者。
引发一个 审计事件
nntplib.connect
,附带参数self
,host
,port
。引发一个 审计事件
nntplib.putline
,附带参数self
,line
。在 3.2 版本加入.
在 3.4 版本发生变更: 本类现在支持使用
ssl.SSLContext.check_hostname
和 服务器名称指示 (参阅ssl.HAS_SNI
)进行主机名检查。在 3.9 版本发生变更: 如果 timeout 参数设置为 0,创建非阻塞套接字时,它将引发
ValueError
来阻止该操作。
- exception nntplib.NNTPError¶
- 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
对象支持以下方法和属性。
属性¶
方法¶
作为几乎全部方法所返回元组的第一项返回的 response 是服务器的响应:以三位数字代码打头的字符串。 如果服务器的响应是提示错误,则方法将引发上述异常之一。
以下方法中许多都接受一个可选的仅限关键字参数 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 为真值,则会在可能的情况下使用来自~/.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
和 服务器名称指示 (参见ssl.HAS_SNI
) 进行主机名检查。
- NNTP.newgroups(date, *, file=None)¶
发送
NEWGROUPS
命令。 date 参数应为datetime.date
或datetime.datetime
对象。 返回一个(response, groups)
对,其中 groups 是代表给定i 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 为消息 ID 列表。此命令经常会被 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 为 RFC 3977 中规定的 wildmat 字符串(它实际上与 DOS 或 UNIX shell 通配字符串相同)。 返回一个(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 可以是表示消息 ID 的字符串,或是指明当前新闻组内文章范围的数字元组(first, last)
,或是指明当前新闻组内从(first, None)
first 到最后一篇文章的元组,或者为None
表示选定当前新闻组内的当前文章。返回一个
(response, overviews)
对。 其中 overviews 是一个包含(article_number, overview)
元组的列表,每个元组对应 message_spec 所选定的一篇文章。 每个 overview 则是包含同样数量条目的字典,但具体数量取决于服务器。 这些条目或是为消息标头(对应键为小写的标头名称)或是为 metadata 项(对应键为以":"
打头的 metadata 名称)。 以下条目会由 NNTP 规范描述来确保提供:subject
,from
,date
,message-id
和references
标头:bytes
metadata: 整个原始文章数据的字节数(包括标头和消息体):lines
metadata: 文章消息体的行数
每个条目的值或者为字符串,或者在没有值时为
None
。建议在标头值可能包含非 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?= <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 为消息 ID (包裹在'<'
和'>'
中) 或者当前新闻组中的文章编号。 如果 message_spec 被省略或为None
,则会选择当前新闻组中的当前文章。 反回一个三元组(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, '<20030112190404.GE29873@epoch.metaslash.com>')
- NNTP.article(message_spec=None, *, file=None)¶
发送
ARTICLE
命令,其中 message_spec 的含义与stat()
中的相同。 返回一个元组(response, info)
,其中 info 是一个namedtuple
,包含三个属性 number, message_id 和 lines (按此顺序)。 number 是新闻组中的文章数量 (或者如果该信息不可用则为 0),message_id 为字符串形式的消息 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 参数是以二进制读取模式打开的 file object,或是任意包含字节串对象的可迭代对象 (表示要发布的文章的原始行数据)。 它应当代表一篇适当格式的新闻组文章,包含所需的标头。post()
方法会自动对以.
打头的行数据进行转义并添加结束行。如果此方法执行成功,将返回服务器的响应。 如果服务器拒绝响应,则会引发
NNTPReplyError
。
- NNTP.ihave(message_id, data)¶
发送
IHAVE
命令。 message_id 为要发给服务器的消息 ID (包裹在'<'
和'>'
中)。 data 形参和返回值与post()
的一致。
- NNTP.slave()¶
发送
SLAVE
命令。 返回服务器的 响应。
- NNTP.set_debuglevel(level)¶
设置实例的调试级别。 它控制着打印调试输出信息的数量。 默认值
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 是该文章的请求标头。 如果提供了 file 形参,则XHDR
命令的输出会保存到文件中。 如果 file 为字符串,则此方法将打开指定名称的文件,向其写入内容并将其关闭。 如果 file 为 file object,则将在该文件对象上调用write()
方法来保存命令所输出的行信息。 如果提供了 file,则返回的 list 将为空列表。
工具函数¶
这个模块还定义了下列工具函数:
- 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'