asyncio 无法读取 Windows 上的标准输入

aysncio cannot read stdin on Windows

我正在尝试在 Windows 7 64 位和 Python 3.4.3

上异步读取标准输入

我受 SO answer:

的启发尝试了这个
import asyncio
import sys


def reader():
    print('Received:', sys.stdin.readline())


loop = asyncio.get_event_loop()
task = loop.add_reader(sys.stdin.fileno(), reader)
loop.run_forever()
loop.close()

但是,它引发了 OSError: [WInError 100381] An operation was attempted on something that is not a socket

stdin 这样的类文件对象可以用 class 包装起来,给它一个套接字的 API 吗?我有 asked this question separately,但如果解决方案很简单,请在这里回答。

假设我不能包装一个类似文件的对象使其成为套接字,我尝试使用受 this gist 启发的流:

import asyncio
import sys


@asyncio.coroutine
def stdio(loop):
    reader = asyncio.StreamReader(loop=loop)
    reader_protocol = asyncio.StreamReaderProtocol(reader)
    yield from loop.connect_read_pipe(lambda: reader_protocol, sys.stdin)


@asyncio.coroutine
def async_input(loop):
    reader = yield from stdio(loop)
    line = yield from reader.readline()
    return line.decode().replace('\r', '').replace('\n', '')


@asyncio.coroutine
def main(loop):
    name = yield from async_input(loop)
    print('Hello ', name)


loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
loop.close()

这在 asyncio.base_events._make_read_pipe_transport

中引发了 NotImplementedError

请告知如何在 Windows 上使用 asyncio 阅读 stdin...

引发 NotImplementedError 异常是因为 connect pipes coroutines are not supported by the SelectorEventLoop, which is the default event loop set on asyncio. You need to use a ProactorEventLoop 支持 Windows 上的管道。但是,它仍然无法工作,因为显然 connect_read_pipeconnect_write_pipe 函数不支持 stdin/stdout/stderr 或 [=33= 中的文件] 作为 Python 3.5.1.

使用异步行为从 stdin 中读取的一种方法是使用具有循环 run_in_executor 方法的线程。这里有一个简单的例子供参考:

import asyncio
import sys

async def aio_readline(loop):
    while True:
        line = await loop.run_in_executor(None, sys.stdin.readline)
        print('Got line:', line, end='')

loop = asyncio.get_event_loop()
loop.run_until_complete(aio_readline(loop))
loop.close()

在示例中,loop.run_in_executor 方法在另一个线程中调用函数 sys.stdin.readline()。线程保持阻塞直到 stdin 收到换行符,同时循环可以自由执行其他协程(如果存在)。