Streams —Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.9/library/asyncio-stream
移動先:案内検索

ストリーム

ソースコード: :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エコークライアントプロトコルの例では、低レベルのloop.create_connection()メソッドを使用しています。


ストリームを使用する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)

    addrs = ', '.join(str(sock.getsockname()) for sock in server.sockets)
    print(f'Serving on {addrs}')

    async with server:
        await server.serve_forever()

asyncio.run(main())

も参照してください

TCPエコーサーバープロトコルの例では、loop.create_server()メソッドを使用しています。


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()メソッドを使用してファイル記述子を監視します。