connect_read_pipe is an asyncio event-loop coroutine for connecting a protocol to a file-like pipe. It lets standard input feed a StreamReader, replacing blocking input() with awaitable readline() calls so background tasks can continue running. section 8.4
The connection uses three cooperating pieces:
- A pipe supplies data; sys.stdin is the file-like pipe used for console input. section 8.4
- A protocol factory creates the protocol that receives data from the pipe. section 8.4
- StreamReaderProtocol delegates received data to a StreamReader, whose readline() coroutine can be awaited. section 8.4
Asynchronous console input
Create a StreamReader and StreamReaderProtocol, then await loop.connect_read_pipe(lambda: protocol, sys.stdin). Repeatedly await stdin_reader.readline() and schedule work with asyncio.create_task(). section 8.4
Listing 8.5 An asynchronous standard input reader
import asyncio
from asyncio import StreamReader
import sys
async def create_stdin_reader() -> StreamReader:
stream_reader = asyncio.StreamReader()
protocol = asyncio.StreamReaderProtocol(stream_reader)
loop = asyncio.get_running_loop()
await loop.connect_read_pipe(lambda: protocol, sys.stdin)
return stream_reader
Shows the helper that connects sys.stdin to a StreamReader. section 8.4
Listing 8.6 Using stream readers for input
import asyncio
from chapter_08.listing_8_5 import create_stdin_reader
from util import delay
async def main():
stdin_reader = await create_stdin_reader()
while True:
delay_time = await stdin_reader.readline()
asyncio.create_task(delay(int(delay_time)))
asyncio.run(main())
Shows readline-based input driving concurrently scheduled delays. section 8.4
