A stream writer is an asyncio object for sending data through a network stream. It hides socket details behind a small interface and is usually paired with a StreamReader for receiving data. section 8.0 section 8.3
Use a stream writer to:
- Send bytes with write(); the method is immediate and is not a coroutine. section 8.3
- Represent a connected client in server callbacks, so application code can send responses or notifications. section 8.5
- Store connected writers to broadcast messages to multiple clients. section 8.5 section 8.6
Sending an HTTP request
Obtain a reader and writer with await asyncio.open_connection(host, port), encode the request, call stream_writer.write(request), and await stream_writer.drain(). Read the response through the paired StreamReader. section 8.3
Listing 8.3 A HTTP request with stream readers and writers
import asyncio
from asyncio import StreamReader
from typing import AsyncGenerator
async def read_until_empty(stream_reader: StreamReader) -> AsyncGenerator[str, None]:
while response := await stream_reader.readline(): #1
yield response.decode()
async def main():
host: str = 'www .example .com'
request: str = f"GET / HTTP/1.1\r\n" \
f"Connection: close\r\n" \
f"Host: {host}\r\n\r\n"
stream_reader, stream_writer = await asyncio.open_connection('www .example .com', 80)
try:
stream_writer.write(request.encode()) #2
await stream_writer.drain()
responses = [response async for response in read_until_empty(stream_reader)] #3
print(''.join(responses))
finally:
stream_writer.close() #4
await stream_writer.wait_closed()
asyncio.run(main())
Inspect the complete HTTP example to see connection creation, request encoding, write(), drain(), and asynchronous response reading together. section 8.3
