“Python/docs/3.9/library/asynchat”的版本间差异
(autoload) |
小 (Page commit) |
||
第1行: | 第1行: | ||
+ | {{DISPLAYTITLE:asynchat — 异步套接字命令/响应处理程序 — Python 文档}} | ||
<div id="module-asynchat" class="section"> | <div id="module-asynchat" class="section"> | ||
<span id="asynchat-asynchronous-socket-command-response-handler"></span> | <span id="asynchat-asynchronous-socket-command-response-handler"></span> | ||
− | = | + | = asynchat — 异步套接字命令/响应处理程序 = |
− | ''' | + | '''源代码:''' [[#id1|<span id="id2" class="problematic">:source:`Lib/asynchat.py`</span>]] |
<div class="deprecated"> | <div class="deprecated"> | ||
− | <span class="versionmodified deprecated">3.6 | + | <span class="versionmodified deprecated"> 自 3.6 版起已弃用:</span>请改用 [[../asyncio#module-asyncio|asyncio]]。 |
</div> | </div> | ||
+ | |||
+ | ----- | ||
+ | |||
<div class="admonition note"> | <div class="admonition note"> | ||
− | + | 笔记 | |
− | + | 该模块的存在只是为了向后兼容。 对于新代码,我们建议使用 [[../asyncio#module-asyncio|asyncio]]。 | |
− | |||
</div> | </div> | ||
− | + | 该模块建立在 [[../asyncore#module-asyncore|asyncore]] 基础架构上,简化了异步客户端和服务器,并使其更容易处理元素由任意字符串终止或长度可变的协议。 [[#module-asynchat|asynchat]] 定义了您子类化的抽象类 [[#asynchat.async_chat|async_chat]],提供了 <code>collect_incoming_data()</code> 和 <code>found_terminator()</code> 方法的实现。 它使用与[[../asyncore#module-asyncore|asyncore]]相同的异步循环,两种类型的通道[[../asyncore#asyncore|asyncore.dispatcher]]和[[#asynchat.async_chat|asynchat.async_chat]]可以在通道图中自由混合. 通常,[[../asyncore#asyncore|asyncore.dispatcher]] 服务器通道在接收传入连接请求时生成新的 [[#asynchat.async_chat|asynchat.async_chat]] 通道对象。 | |
− | |||
− | |||
− | [[#module-asynchat| | ||
− | |||
− | <code>found_terminator()</code> | ||
− | [[../asyncore#module-asyncore| | ||
− | |||
− | |||
− | [[#asynchat.async_chat| | ||
− | |||
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">asynchat.</span></span><span class="sig-name descname"><span class="pre">async_chat</span></span></dt> |
− | <dd><p> | + | <dd><p>此类是 [[../asyncore#asyncore|asyncore.dispatcher]] 的抽象子类。 要实际使用代码,您必须将 [[#asynchat.async_chat|async_chat]] 子类化,提供有意义的 [[#asynchat.async_chat.collect_incoming_data|collect_incoming_data()]] 和 [[#asynchat.async_chat.found_terminator|found_terminator()]] 方法。 可以使用 [[../asyncore#asyncore|asyncore.dispatcher]] 方法,尽管在消息/响应上下文中并非所有方法都有意义。</p> |
− | + | <p>与 [[../asyncore#asyncore|asyncore.dispatcher]] 一样,[[#asynchat.async_chat|async_chat]] 定义了一组事件,这些事件在 <code>select()</code> 调用后通过对套接字条件的分析生成。 一旦轮询循环开始,事件处理框架就会调用 [[#asynchat.async_chat|async_chat]] 对象的方法,而程序员无需采取任何行动。</p> | |
− | + | <p>可以修改两个类属性,以提高性能,甚至可能节省内存。</p> | |
− | |||
− | |||
− | |||
− | <p> | ||
− | |||
− | <code>select()</code> | ||
− | [[#asynchat.async_chat| | ||
− | |||
− | <p> | ||
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">ac_in_buffer_size</span></span></dt> |
− | <dd><p> | + | <dd><p>异步输入缓冲区大小(默认 <code>4096</code>)。</p></dd></dl> |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">ac_out_buffer_size</span></span></dt> |
− | <dd><p> | + | <dd><p>异步输出缓冲区大小(默认 <code>4096</code>)。</p></dd></dl> |
− | <p> | + | <p>与 [[../asyncore#asyncore|asyncore.dispatcher]] 不同,[[#asynchat.async_chat|async_chat]] 允许您定义 ''producers'' 的 FIFO 队列。 生产者只需要一种方法,<code>more()</code>,它应该返回要在通道上传输的数据。 生产者通过让其 <code>more()</code> 方法返回空字节对象来表示耗尽(''即''它不包含更多数据)。 此时,[[#asynchat.async_chat|async_chat]] 对象从队列中删除生产者并开始使用下一个生产者(如果有)。 当生产者队列为空时,<code>handle_write()</code> 方法什么也不做。 您可以使用通道对象的 [[#asynchat.async_chat.set_terminator|set_terminator()]] 方法来描述如何识别来自远程端点的传入传输的结束或重要断点。</p> |
− | + | <p>要构建一个功能正常的 [[#asynchat.async_chat|async_chat]] 子类,您的输入方法 [[#asynchat.async_chat.collect_incoming_data|collect_incoming_data()]] 和 [[#asynchat.async_chat.found_terminator|found_terminator()]] 必须处理通道异步接收的数据。 方法描述如下。</p></dd></dl> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | <code>handle_write()</code> | ||
− | [[#asynchat.async_chat.set_terminator| | ||
− | |||
− | |||
− | <p> | ||
− | [[#asynchat.async_chat.collect_incoming_data| | ||
− | |||
− | |||
− | ; < | + | ; <span class="sig-prename descclassname"><span class="pre">async_chat.</span></span><span class="sig-name descname"><span class="pre">close_when_done</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> |
− | : | + | : 将 <code>None</code> 推送到生产者队列。 当这个生产者从队列中弹出时,它会导致通道关闭。 |
− | ; < | + | ; <span class="sig-prename descclassname"><span class="pre">async_chat.</span></span><span class="sig-name descname"><span class="pre">collect_incoming_data</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">data</span></span>''<span class="sig-paren">)</span> |
− | : | + | : 调用 ''data'' 保存任意数量的接收数据。 必须覆盖的默认方法会引发 [[../exceptions#NotImplementedError|NotImplementedError]] 异常。 |
− | ; < | + | ; <span class="sig-prename descclassname"><span class="pre">async_chat.</span></span><span class="sig-name descname"><span class="pre">discard_buffers</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> |
− | : | + | : 在紧急情况下,此方法将丢弃输入和/或输出缓冲区和生产者队列中保存的任何数据。 |
− | ; < | + | ; <span class="sig-prename descclassname"><span class="pre">async_chat.</span></span><span class="sig-name descname"><span class="pre">found_terminator</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> |
− | : | + | : 当传入数据流与 [[#asynchat.async_chat.set_terminator|set_terminator()]] 设置的终止条件匹配时调用。 必须覆盖的默认方法会引发 [[../exceptions#NotImplementedError|NotImplementedError]] 异常。 缓冲的输入数据应该通过实例属性可用。 |
− | ; < | + | ; <span class="sig-prename descclassname"><span class="pre">async_chat.</span></span><span class="sig-name descname"><span class="pre">get_terminator</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> |
− | : | + | : 返回通道的当前终止符。 |
− | ; < | + | ; <span class="sig-prename descclassname"><span class="pre">async_chat.</span></span><span class="sig-name descname"><span class="pre">push</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">data</span></span>''<span class="sig-paren">)</span> |
− | : | + | : 将数据推送到通道的队列以确保其传输。 这就是让通道将数据写入网络所需要做的全部工作,尽管可以在更复杂的方案中使用您自己的生产者来实现加密和分块,例如。 |
− | ; < | + | ; <span class="sig-prename descclassname"><span class="pre">async_chat.</span></span><span class="sig-name descname"><span class="pre">push_with_producer</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">producer</span></span>''<span class="sig-paren">)</span> |
− | : | + | : 获取一个生产者对象并将其添加到与通道关联的生产者队列中。 当所有当前推送的生产者都用完时,通道将通过调用其 <code>more()</code> 方法来消耗该生产者的数据并将数据发送到远程端点。 |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-prename descclassname"><span class="pre">async_chat.</span></span><span class="sig-name descname"><span class="pre">set_terminator</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">term</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>设置要在通道上识别的终止条件。 <code>term</code> 可以是三种类型的值中的任何一种,对应三种不同的方式来处理传入的协议数据。</p> |
− | |||
− | |||
{| | {| | ||
− | !width="20%"| <p> | + | !width="20%"| <p>学期</p> |
− | !width="80%"| <p> | + | !width="80%"| <p>描述</p> |
|- | |- | ||
− | | <p>'' | + | | <p>''细绳''</p> |
− | | <p> | + | | <p>当在输入流中找到字符串时将调用 [[#asynchat.async_chat.found_terminator|found_terminator()]]</p> |
− | |||
|- | |- | ||
− | | <p>'' | + | | <p>''整数''</p> |
− | | <p> | + | | <p>当接收到指定数量的字符时,将调用 [[#asynchat.async_chat.found_terminator|found_terminator()]]</p> |
− | |||
− | |||
|- | |- | ||
| <p><code>None</code></p> | | <p><code>None</code></p> | ||
− | | <p> | + | | <p>频道永远持续收集数据</p> |
− | |||
|} | |} | ||
− | <p> | + | <p>请注意,在调用 [[#asynchat.async_chat.found_terminator|found_terminator()]] 后,终止符后面的任何数据都可供通道读取。</p></dd></dl> |
− | |||
<div id="asynchat-example" class="section"> | <div id="asynchat-example" class="section"> | ||
− | <span id=" | + | <span id="id3"></span> |
− | == | + | == 异步示例 == |
− | + | 以下部分示例显示了如何使用 [[#asynchat.async_chat|async_chat]] 读取 HTTP 请求。 Web 服务器可能会为每个传入的客户端连接创建一个 <code>http_request_handler</code> 对象。 请注意,最初将通道终止符设置为匹配 HTTP 标头末尾的空行,并且一个标志表示正在读取标头。 | |
− | [[#asynchat.async_chat| | ||
− | <code>http_request_handler</code> | ||
− | |||
− | |||
− | |||
− | + | 读取标头后,如果请求是 POST 类型(表示输入流中存在更多数据),则 <code>Content-Length:</code> 标头用于设置数字终止符以从中读取正确数量的数据这个频道。 | |
− | |||
− | <code>Content-Length:</code> | ||
− | |||
− | + | 在将通道终止符设置为 <code>None</code> 以确保忽略 Web 客户端发送的任何无关数据后,一旦所有相关输入都被编组,将调用 <code>handle_request()</code> 方法。 | |
− | |||
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第145行: | 第97行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">import asynchat |
class http_request_handler(asynchat.async_chat): | class http_request_handler(asynchat.async_chat): | ||
第154行: | 第106行: | ||
self.sessions = sessions | self.sessions = sessions | ||
self.ibuffer = [] | self.ibuffer = [] | ||
− | self.obuffer = b | + | self.obuffer = b"" |
− | self.set_terminator(b | + | self.set_terminator(b"\r\n\r\n") |
self.reading_headers = True | self.reading_headers = True | ||
self.handling = False | self.handling = False | ||
第162行: | 第114行: | ||
def collect_incoming_data(self, data): | def collect_incoming_data(self, data): | ||
− | + | """Buffer the data""" | |
self.ibuffer.append(data) | self.ibuffer.append(data) | ||
第168行: | 第120行: | ||
if self.reading_headers: | if self.reading_headers: | ||
self.reading_headers = False | self.reading_headers = False | ||
− | self.parse_headers(b | + | self.parse_headers(b"".join(self.ibuffer)) |
self.ibuffer = [] | self.ibuffer = [] | ||
− | if self.op.upper() == b | + | if self.op.upper() == b"POST": |
− | clen = self.headers.getheader( | + | clen = self.headers.getheader("content-length") |
self.set_terminator(int(clen)) | self.set_terminator(int(clen)) | ||
else: | else: | ||
第179行: | 第131行: | ||
elif not self.handling: | elif not self.handling: | ||
self.set_terminator(None) # browsers sometimes over-send | self.set_terminator(None) # browsers sometimes over-send | ||
− | self.cgi_data = parse(self.headers, b | + | self.cgi_data = parse(self.headers, b"".join(self.ibuffer)) |
self.handling = True | self.handling = True | ||
self.ibuffer = [] | self.ibuffer = [] | ||
− | self.handle_request()</ | + | self.handle_request()</syntaxhighlight> |
+ | |||
+ | </div> | ||
</div> | </div> | ||
第189行: | 第143行: | ||
</div> | </div> | ||
+ | <div class="clearer"> | ||
+ | |||
+ | |||
</div> | </div> | ||
− | [[Category:Python 3.9 | + | [[Category:Python 3.9 文档]] |
2021年10月31日 (日) 04:51的最新版本
asynchat — 异步套接字命令/响应处理程序
源代码: :source:`Lib/asynchat.py`
自 3.6 版起已弃用:请改用 asyncio。
该模块建立在 asyncore 基础架构上,简化了异步客户端和服务器,并使其更容易处理元素由任意字符串终止或长度可变的协议。 asynchat 定义了您子类化的抽象类 async_chat,提供了 collect_incoming_data()
和 found_terminator()
方法的实现。 它使用与asyncore相同的异步循环,两种类型的通道asyncore.dispatcher和asynchat.async_chat可以在通道图中自由混合. 通常,asyncore.dispatcher 服务器通道在接收传入连接请求时生成新的 asynchat.async_chat 通道对象。
- class asynchat.async_chat
此类是 asyncore.dispatcher 的抽象子类。 要实际使用代码,您必须将 async_chat 子类化,提供有意义的 collect_incoming_data() 和 found_terminator() 方法。 可以使用 asyncore.dispatcher 方法,尽管在消息/响应上下文中并非所有方法都有意义。
与 asyncore.dispatcher 一样,async_chat 定义了一组事件,这些事件在
select()
调用后通过对套接字条件的分析生成。 一旦轮询循环开始,事件处理框架就会调用 async_chat 对象的方法,而程序员无需采取任何行动。可以修改两个类属性,以提高性能,甚至可能节省内存。
- ac_in_buffer_size
异步输入缓冲区大小(默认
4096
)。
- ac_out_buffer_size
异步输出缓冲区大小(默认
4096
)。
与 asyncore.dispatcher 不同,async_chat 允许您定义 producers 的 FIFO 队列。 生产者只需要一种方法,
more()
,它应该返回要在通道上传输的数据。 生产者通过让其more()
方法返回空字节对象来表示耗尽(即它不包含更多数据)。 此时,async_chat 对象从队列中删除生产者并开始使用下一个生产者(如果有)。 当生产者队列为空时,handle_write()
方法什么也不做。 您可以使用通道对象的 set_terminator() 方法来描述如何识别来自远程端点的传入传输的结束或重要断点。要构建一个功能正常的 async_chat 子类,您的输入方法 collect_incoming_data() 和 found_terminator() 必须处理通道异步接收的数据。 方法描述如下。
- async_chat.close_when_done()
- 将
None
推送到生产者队列。 当这个生产者从队列中弹出时,它会导致通道关闭。
- async_chat.collect_incoming_data(data)
- 调用 data 保存任意数量的接收数据。 必须覆盖的默认方法会引发 NotImplementedError 异常。
- async_chat.discard_buffers()
- 在紧急情况下,此方法将丢弃输入和/或输出缓冲区和生产者队列中保存的任何数据。
- async_chat.found_terminator()
- 当传入数据流与 set_terminator() 设置的终止条件匹配时调用。 必须覆盖的默认方法会引发 NotImplementedError 异常。 缓冲的输入数据应该通过实例属性可用。
- async_chat.get_terminator()
- 返回通道的当前终止符。
- async_chat.push(data)
- 将数据推送到通道的队列以确保其传输。 这就是让通道将数据写入网络所需要做的全部工作,尽管可以在更复杂的方案中使用您自己的生产者来实现加密和分块,例如。
- async_chat.push_with_producer(producer)
- 获取一个生产者对象并将其添加到与通道关联的生产者队列中。 当所有当前推送的生产者都用完时,通道将通过调用其
more()
方法来消耗该生产者的数据并将数据发送到远程端点。
- async_chat.set_terminator(term)
设置要在通道上识别的终止条件。
term
可以是三种类型的值中的任何一种,对应三种不同的方式来处理传入的协议数据。学期
描述
细绳
当在输入流中找到字符串时将调用 found_terminator()
整数
当接收到指定数量的字符时,将调用 found_terminator()
None
频道永远持续收集数据
请注意,在调用 found_terminator() 后,终止符后面的任何数据都可供通道读取。
异步示例
以下部分示例显示了如何使用 async_chat 读取 HTTP 请求。 Web 服务器可能会为每个传入的客户端连接创建一个 http_request_handler
对象。 请注意,最初将通道终止符设置为匹配 HTTP 标头末尾的空行,并且一个标志表示正在读取标头。
读取标头后,如果请求是 POST 类型(表示输入流中存在更多数据),则 Content-Length:
标头用于设置数字终止符以从中读取正确数量的数据这个频道。
在将通道终止符设置为 None
以确保忽略 Web 客户端发送的任何无关数据后,一旦所有相关输入都被编组,将调用 handle_request()
方法。