ストリーム
ソースコード: :source: `Lib / asyncio / streams.py`
ストリームは、ネットワーク接続で機能する高レベルの非同期/待機対応プリミティブです。 ストリームを使用すると、コールバックや低レベルのプロトコルやトランスポートを使用せずにデータを送受信できます。
asyncioストリームを使用して記述されたTCPエコークライアントの例を次に示します。
import asyncio
async def tcp_echo_client(message):
reader, writer = await asyncio.open_connection(
'127.0.0.1', 8888)
print(f'Send: {message!r}')
writer.write(message.encode())
await writer.drain()
data = await reader.read(100)
print(f'Received: {data.decode()!r}')
print('Close the connection')
writer.close()
await writer.wait_closed()
asyncio.run(tcp_echo_client('Hello World!'))
以下の例セクションも参照してください。
流れ関数
次のトップレベルの非同期関数を使用して、ストリームを作成および操作できます。
Unixソケット
StreamReader
- class asyncio.StreamReader
IOストリームからデータを読み取るためのAPIを提供するリーダーオブジェクトを表します。
StreamReader オブジェクトを直接インスタンス化することはお勧めしません。 代わりに
open_connection()
とstart_server()
を使用してください。- at_eof()
バッファが空で
feed_eof()
が呼び出された場合は、True
を返します。
StreamWriter
- class asyncio.StreamWriter
IOストリームにデータを書き込むためのAPIを提供するライターオブジェクトを表します。
StreamWriter オブジェクトを直接インスタンス化することはお勧めしません。 代わりに
open_connection()
とstart_server()
を使用してください。- write(data)
このメソッドは、 data を基になるソケットにすぐに書き込もうとします。 それが失敗した場合、データは送信できるようになるまで内部書き込みバッファのキューに入れられます。
この方法は、
drain()
方法と一緒に使用する必要があります。stream.write(data) await stream.drain()
- writelines(data)
このメソッドは、バイトのリスト(または反復可能なもの)を基になるソケットにすぐに書き込みます。 それが失敗した場合、データは送信できるようになるまで内部書き込みバッファのキューに入れられます。
この方法は、
drain()
方法と一緒に使用する必要があります。stream.writelines(lines) await stream.drain()
- close()
このメソッドは、ストリームと基になるソケットを閉じます。
この方法は、
wait_closed()
方法と一緒に使用する必要があります。stream.close() await stream.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エコークライアント:
import asyncio
async def tcp_echo_client(message):
reader, writer = await asyncio.open_connection(
'127.0.0.1', 8888)
print(f'Send: {message!r}')
writer.write(message.encode())
data = await reader.read(100)
print(f'Received: {data.decode()!r}')
print('Close the connection')
writer.close()
asyncio.run(tcp_echo_client('Hello World!'))
ストリームを使用するTCPエコーサーバー
asyncio.start_server()
機能を使用するTCPエコーサーバー:
import asyncio
async def handle_echo(reader, writer):
data = await reader.read(100)
message = data.decode()
addr = writer.get_extra_info('peername')
print(f"Received {message!r} from {addr!r}")
print(f"Send: {message!r}")
writer.write(data)
await writer.drain()
print("Close the connection")
writer.close()
async def main():
server = await asyncio.start_server(
handle_echo, '127.0.0.1', 8888)
addr = server.sockets[0].getsockname()
print(f'Serving on {addr}')
async with server:
await server.serve_forever()
asyncio.run(main())
HTTPヘッダーを取得する
コマンドラインで渡されたURLのHTTPヘッダーをクエリする簡単な例:
import asyncio
import urllib.parse
import sys
async def print_http_headers(url):
url = urllib.parse.urlsplit(url)
if url.scheme == 'https':
reader, writer = await asyncio.open_connection(
url.hostname, 443, ssl=True)
else:
reader, writer = await asyncio.open_connection(
url.hostname, 80)
query = (
f"HEAD {url.path or '/'} HTTP/1.0\r\n"
f"Host: {url.hostname}\r\n"
f"\r\n"
)
writer.write(query.encode('latin-1'))
while True:
line = await reader.readline()
if not line:
break
line = line.decode('latin1').rstrip()
if line:
print(f'HTTP header> {line}')
# Ignore the body, close the socket
writer.close()
url = sys.argv[1]
asyncio.run(print_http_headers(url))
使用法:
python example.py http://example.com/path/page.html
またはHTTPSの場合:
python example.py https://example.com/path/page.html
開いているソケットを登録して、ストリームを使用してデータを待機します
ソケットがopen_connection()
関数を使用してデータを受信するまで待機するコルーチン:
import asyncio
import socket
async def wait_for_data():
# Get a reference to the current event loop because
# we want to access low-level APIs.
loop = asyncio.get_running_loop()
# Create a pair of connected sockets.
rsock, wsock = socket.socketpair()
# Register the open socket to wait for data.
reader, writer = await asyncio.open_connection(sock=rsock)
# Simulate the reception of data from the network
loop.call_soon(wsock.send, 'abc'.encode())
# Wait for data
data = await reader.read(100)
# Got data, we are done: close the socket
print("Received:", data.decode())
writer.close()
# Close the second socket
wsock.close()
asyncio.run(wait_for_data())
も参照してください
プロトコルを使用してデータを待機するためにオープンソケットを登録する例では、低レベルプロトコルとloop.create_connection()
メソッドを使用します。
読み取りイベントのファイル記述子を監視するの例では、低レベルの loop.add_reader()メソッドを使用してファイル記述子を監視します。