我正在尝试在Windows 7 64位和Python 3.4.3上asynchronous读取stdin
我尝试了这个启发的答案 :
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
这样的类似文件的对象可以被包装在一个类中来给它一个套接字的API吗? 我已经单独提出了这个问题 ,但是如果解决方法很简单,请在这里回答。
假设我不能包装一个类似文件的对象来使它成为一个套接字,我尝试使用stream的灵感来源于这个要点 :
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
请告知如何阅读stdin
在Windows上使用asyncio
…
引发NotImplementedError
异常是因为SelectorEventLoop
不支持连接管道协程 ,这是在asyncio
设置的默认事件循环。 您需要使用ProactorEventLoop
来支持Windows上的管道。 但是,它仍然不起作用,因为显然connect_read_pipe
和connect_write_pipe
函数不支持stdin
/ stdout
/ stderr
或Windows中的文件,如Python 3.5.1。
从stdin
读取异步行为的run_in_executor
方法是使用循环的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()
在这个例子中,函数sys.stdin.readline()
在另一个线程中被loop.run_in_executor
方法调用。 线程一直处于阻塞状态,直到stdin
接收到一个换行符,同时循环可以自由地执行其他的协程。