“Python/docs/3.9/library/asyncio-stream”的版本间差异
(autoload) |
小 (Page commit) |
||
第1行: | 第1行: | ||
+ | {{DISPLAYTITLE:流 — Python 文档}} | ||
<div id="streams" class="section"> | <div id="streams" class="section"> | ||
<span id="asyncio-streams"></span> | <span id="asyncio-streams"></span> | ||
− | = | + | = 流 = |
− | ''' | + | '''源代码:''' [[#id1|<span id="id2" class="problematic">:source:`Lib/asyncio/streams.py`</span>]] |
− | |||
− | |||
− | |||
− | + | ----- | |
− | + | ||
+ | 流是用于处理网络连接的高级异步/等待就绪原语。 流允许在不使用回调或低级协议和传输的情况下发送和接收数据。 | ||
+ | |||
+ | 下面是一个使用 asyncio 流编写的 TCP 回显客户端的示例: | ||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第17行: | 第18行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">import asyncio |
async def tcp_echo_client(message): | async def tcp_echo_client(message): | ||
第34行: | 第35行: | ||
await writer.wait_closed() | await writer.wait_closed() | ||
− | asyncio.run(tcp_echo_client('Hello World!'))</ | + | asyncio.run(tcp_echo_client('Hello World!'))</syntaxhighlight> |
− | |||
− | |||
</div> | </div> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</div> | </div> | ||
− | + | 另请参阅下面的 [[#examples|示例]] 部分。 | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | 流函数 | |
− | |||
− | + | 以下顶级异步函数可用于创建和处理流: | |
− | + | Unix 套接字 | |
<div id="streamreader" class="section"> | <div id="streamreader" class="section"> | ||
− | == | + | == 流阅读器 == |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<dl> | <dl> | ||
− | <dt>'' | + | <dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">asyncio.</span></span><span class="sig-name descname"><span class="pre">StreamReader</span></span></dt> |
− | + | <dd><p>表示提供 API 以从 IO 流读取数据的读取器对象。</p> | |
− | < | + | <p>不建议直接实例化''StreamReader''对象; 改用 <code>open_connection()</code> 和 <code>start_server()</code>。</p> |
− | |||
− | |||
− | <p> | ||
− | |||
− | |||
− | <p> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">at_eof</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>如果缓冲区为空并且 <code>feed_eof()</code> 被调用,则返回 <code>True</code>。</p></dd></dl> |
− | |||
</dd></dl> | </dd></dl> | ||
第188行: | 第65行: | ||
<div id="streamwriter" class="section"> | <div id="streamwriter" class="section"> | ||
− | == | + | == 流写入器 == |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">asyncio.</span></span><span class="sig-name descname"><span class="pre">StreamWriter</span></span></dt> |
− | <dd><p> | + | <dd><p>表示提供 API 以将数据写入 IO 流的编写器对象。</p> |
− | + | <p>不建议直接实例化''StreamWriter''对象; 改用 <code>open_connection()</code> 和 <code>start_server()</code>。</p> | |
− | <p> | ||
− | |||
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">write</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">data</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>该方法尝试立即将 ''data'' 写入底层套接字。 如果失败,数据将在内部写入缓冲区中排队,直到可以发送为止。</p> |
− | + | <p>该方法应与 <code>drain()</code> 方法一起使用:</p> | |
− | |||
− | <p> | ||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">stream.write(data) |
− | await stream.drain()</ | + | await stream.drain()</syntaxhighlight> |
</div> | </div> | ||
第215行: | 第87行: | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">writelines</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">data</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>该方法立即将字节列表(或任何可迭代的)写入底层套接字。 如果失败,数据将在内部写入缓冲区中排队,直到可以发送为止。</p> |
− | + | <p>该方法应与 <code>drain()</code> 方法一起使用:</p> | |
− | |||
− | |||
− | <p> | ||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">stream.writelines(lines) |
− | await stream.drain()</ | + | await stream.drain()</syntaxhighlight> |
</div> | </div> | ||
第233行: | 第102行: | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">close</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>该方法关闭流和底层套接字。</p> |
− | <p> | + | <p>该方法应与 <code>wait_closed()</code> 方法一起使用:</p> |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">stream.close() |
− | await stream.wait_closed()</ | + | await stream.wait_closed()</syntaxhighlight> |
</div> | </div> | ||
第248行: | 第117行: | ||
<dl> | <dl> | ||
− | <dt | + | <dt><span class="sig-name descname"><span class="pre">can_write_eof</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | + | <dd><p>如果底层传输支持 [[#asyncio.StreamWriter.write_eof|write_eof()]] 方法,则返回 <code>True</code>,否则返回 <code>False</code>。</p></dd></dl> | |
− | |||
− | |||
− | |||
− | |||
− | <dd><p> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
<dl> | <dl> | ||
− | <dt | + | <dt><span class="sig-name descname"><span class="pre">write_eof</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>缓冲的写入数据刷新后关闭流的写入端。</p></dd></dl> |
− | |||
<dl> | <dl> | ||
− | <dt | + | <dt><span class="sig-name descname"><span class="pre">transport</span></span></dt> |
− | + | <dd><p>返回底层异步传输。</p></dd></dl> | |
− | |||
− | < | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | <p> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">get_extra_info</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">default</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt> |
− | < | + | <dd><p>访问可选的交通信息; 有关详细信息,请参阅 [[../asyncio-protocol#asyncio.BaseTransport|BaseTransport.get_extra_info()]]。</p></dd></dl> |
− | |||
− | < | ||
− | |||
− | < | ||
− | |||
− | </ | ||
<dl> | <dl> | ||
− | <dt> | + | <dt><span class="sig-name descname"><span class="pre">is_closing</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>如果流已关闭或正在关闭,则返回 <code>True</code>。</p> |
− | |||
− | |||
<div class="versionadded"> | <div class="versionadded"> | ||
− | <p><span class="versionmodified added">3.7 | + | <p><span class="versionmodified added">3.7 版中的新功能。</span></p> |
</div></dd></dl> | </div></dd></dl> | ||
第313行: | 第146行: | ||
<div id="examples" class="section"> | <div id="examples" class="section"> | ||
− | == | + | == 例子 == |
<div id="tcp-echo-client-using-streams" class="section"> | <div id="tcp-echo-client-using-streams" class="section"> | ||
<span id="asyncio-tcp-echo-client-streams"></span> | <span id="asyncio-tcp-echo-client-streams"></span> | ||
− | === TCP | + | === 使用流的 TCP 回显客户端 === |
− | + | 使用 <code>asyncio.open_connection()</code> 函数的 TCP 回显客户端: | |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第326行: | 第159行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">import asyncio |
async def tcp_echo_client(message): | async def tcp_echo_client(message): | ||
第341行: | 第174行: | ||
writer.close() | writer.close() | ||
− | asyncio.run(tcp_echo_client('Hello World!'))</ | + | asyncio.run(tcp_echo_client('Hello World!'))</syntaxhighlight> |
</div> | </div> | ||
第348行: | 第181行: | ||
<div class="admonition seealso"> | <div class="admonition seealso"> | ||
− | + | 也可以看看 | |
− | + | [[../asyncio-protocol#asyncio-example-tcp-echo-client-protocol|TCP 回显客户端协议]] 示例使用低级 <code>loop.create_connection()</code> 方法。 | |
− | |||
第360行: | 第192行: | ||
<span id="asyncio-tcp-echo-server-streams"></span> | <span id="asyncio-tcp-echo-server-streams"></span> | ||
− | === TCP | + | === 使用流的 TCP 回显服务器 === |
− | + | 使用 <code>asyncio.start_server()</code> 函数的 TCP 回显服务器: | |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第368行: | 第200行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">import asyncio |
async def handle_echo(reader, writer): | async def handle_echo(reader, writer): | ||
第375行: | 第207行: | ||
addr = writer.get_extra_info('peername') | addr = writer.get_extra_info('peername') | ||
− | print(f | + | print(f"Received {message!r} from {addr!r}") |
− | print(f | + | print(f"Send: {message!r}") |
writer.write(data) | writer.write(data) | ||
await writer.drain() | await writer.drain() | ||
− | print( | + | print("Close the connection") |
writer.close() | writer.close() | ||
第388行: | 第220行: | ||
handle_echo, '127.0.0.1', 8888) | handle_echo, '127.0.0.1', 8888) | ||
− | + | addrs = ', '.join(str(sock.getsockname()) for sock in server.sockets) | |
− | print(f'Serving on { | + | print(f'Serving on {addrs}') |
async with server: | async with server: | ||
await server.serve_forever() | await server.serve_forever() | ||
− | asyncio.run(main())</ | + | asyncio.run(main())</syntaxhighlight> |
</div> | </div> | ||
第401行: | 第233行: | ||
<div class="admonition seealso"> | <div class="admonition seealso"> | ||
− | + | 也可以看看 | |
− | + | [[../asyncio-protocol#asyncio-example-tcp-echo-server-protocol|TCP 回显服务器协议]] 示例使用 <code>loop.create_server()</code> 方法。 | |
− | |||
第412行: | 第243行: | ||
<div id="get-http-headers" class="section"> | <div id="get-http-headers" class="section"> | ||
− | === | + | === 获取 HTTP 标头 === |
− | + | 查询通过命令行传递的 URL 的 HTTP 标头的简单示例: | |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第420行: | 第251行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">import asyncio |
import urllib.parse | import urllib.parse | ||
import sys | import sys | ||
第434行: | 第265行: | ||
query = ( | query = ( | ||
− | f | + | f"HEAD {url.path or '/'} HTTP/1.0\r\n" |
− | f | + | f"Host: {url.hostname}\r\n" |
− | f | + | f"\r\n" |
) | ) | ||
第447行: | 第278行: | ||
line = line.decode('latin1').rstrip() | line = line.decode('latin1').rstrip() | ||
if line: | if line: | ||
− | print(f'HTTP header | + | print(f'HTTP header> {line}') |
# Ignore the body, close the socket | # Ignore the body, close the socket | ||
第453行: | 第284行: | ||
url = sys.argv[1] | url = sys.argv[1] | ||
− | asyncio.run(print_http_headers(url))</ | + | asyncio.run(print_http_headers(url))</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 用法: | |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第464行: | 第295行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">python example.py http://example.com/path/page.html</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 或使用 HTTPS: | |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第475行: | 第306行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">python example.py https://example.com/path/page.html</syntaxhighlight> |
</div> | </div> | ||
第485行: | 第316行: | ||
<span id="asyncio-example-create-connection-streams"></span> | <span id="asyncio-example-create-connection-streams"></span> | ||
− | === | + | === 注册一个打开的套接字以使用流等待数据 === |
− | + | 协程等待套接字使用 <code>open_connection()</code> 函数接收数据: | |
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第494行: | 第324行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">import asyncio |
import socket | import socket | ||
第515行: | 第345行: | ||
# Got data, we are done: close the socket | # Got data, we are done: close the socket | ||
− | print( | + | print("Received:", data.decode()) |
writer.close() | writer.close() | ||
第521行: | 第351行: | ||
wsock.close() | wsock.close() | ||
− | asyncio.run(wait_for_data())</ | + | asyncio.run(wait_for_data())</syntaxhighlight> |
</div> | </div> | ||
第528行: | 第358行: | ||
<div class="admonition seealso"> | <div class="admonition seealso"> | ||
− | + | 也可以看看 | |
+ | |||
+ | [[../asyncio-protocol#asyncio-example-create-connection|注册一个打开的套接字以使用协议等待数据]]示例使用低级协议和<code>loop.create_connection()</code>方法。 | ||
− | + | [[../asyncio-eventloop#asyncio-example-watch-fd|watch a file descriptor for read events]] 示例使用低级 [[../asyncio-eventloop#asyncio.loop|loop.add_reader()]] 方法来监视文件描述符。 | |
− | |||
− | |||
− | |||
+ | </div> | ||
</div> | </div> | ||
第542行: | 第372行: | ||
</div> | </div> | ||
+ | <div class="clearer"> | ||
+ | |||
+ | |||
</div> | </div> | ||
− | [[Category:Python 3.9 | + | [[Category:Python 3.9 文档]] |
2021年10月31日 (日) 04:51的最新版本
流
源代码: :source:`Lib/asyncio/streams.py`
流是用于处理网络连接的高级异步/等待就绪原语。 流允许在不使用回调或低级协议和传输的情况下发送和接收数据。
下面是一个使用 asyncio 流编写的 TCP 回显客户端的示例:
另请参阅下面的 示例 部分。
流函数
以下顶级异步函数可用于创建和处理流:
Unix 套接字
流阅读器
- class asyncio.StreamReader
表示提供 API 以从 IO 流读取数据的读取器对象。
不建议直接实例化StreamReader对象; 改用
open_connection()
和start_server()
。- at_eof()
如果缓冲区为空并且
feed_eof()
被调用,则返回True
。
流写入器
- class asyncio.StreamWriter
表示提供 API 以将数据写入 IO 流的编写器对象。
不建议直接实例化StreamWriter对象; 改用
open_connection()
和start_server()
。- write(data)
该方法尝试立即将 data 写入底层套接字。 如果失败,数据将在内部写入缓冲区中排队,直到可以发送为止。
该方法应与
drain()
方法一起使用:
- writelines(data)
该方法立即将字节列表(或任何可迭代的)写入底层套接字。 如果失败,数据将在内部写入缓冲区中排队,直到可以发送为止。
该方法应与
drain()
方法一起使用:
- close()
该方法关闭流和底层套接字。
该方法应与
wait_closed()
方法一起使用:
- can_write_eof()
如果底层传输支持 write_eof() 方法,则返回
True
,否则返回False
。
- write_eof()
缓冲的写入数据刷新后关闭流的写入端。
- transport
返回底层异步传输。
- get_extra_info(name, default=None)
访问可选的交通信息; 有关详细信息,请参阅 BaseTransport.get_extra_info()。
- is_closing()
如果流已关闭或正在关闭,则返回
True
。3.7 版中的新功能。
例子
使用流的 TCP 回显客户端
使用 asyncio.open_connection()
函数的 TCP 回显客户端:
使用流的 TCP 回显服务器
使用 asyncio.start_server()
函数的 TCP 回显服务器:
获取 HTTP 标头
查询通过命令行传递的 URL 的 HTTP 标头的简单示例:
用法:
或使用 HTTPS:
注册一个打开的套接字以使用流等待数据
协程等待套接字使用 open_connection()
函数接收数据:
也可以看看
注册一个打开的套接字以使用协议等待数据示例使用低级协议和loop.create_connection()
方法。
watch a file descriptor for read events 示例使用低级 loop.add_reader() 方法来监视文件描述符。