2015-07-20 9 views
11

Ich versuche stdin asynchron auf Windows 7 64-Bit und Python 3.4.3aysncio nicht lesen kann stdin auf Windows

Ich versuchte dies inspiriert von einem SO answer zu lesen:

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() 

Es ist jedoch wirft eine OSError: [WInError 100381] An operation was attempted on something that is not a socket.

Könnte ein dateiähnliches Objekt wie stdin in eine Klasse eingebettet werden, um es die API eines Sockets zu geben? Ich habe asked this question separately, aber wenn die Lösung einfach ist, antworten Sie bitte hier.

Unter der Annahme, dass ich nicht eine dateiähnliche Objekt wickeln kann es sich um eine Buchse zu machen, habe ich versucht Streams mit wie this gist inspiriert:

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() 

Und das wirft ein NotImplementedError in asyncio.base_events._make_read_pipe_transport

Bitte beraten, wie zu lesen stdin mit asyncio unter Windows ...

Antwort

10

Die NotImplementedError Ausnahme wird ausgelöst, weil die connect pipes coroutines nicht su sind Wird von der SelectorEventLoop übermittelt, die als Standard-Ereignisschleife auf asyncio festgelegt ist. Sie müssen eine ProactorEventLoop verwenden, um Pipes unter Windows zu unterstützen. Es funktioniert jedoch immer noch nicht, weil die connect_read_pipe und connect_write_pipe Funktionen stdin/stdout/stderr oder Dateien in Windows als Python 3.5.1 nicht unterstützt.

Eine Möglichkeit zum Lesen von stdin mit einem asynchronen Verhalten ist die Verwendung eines Threads mit der run_in_executor Methode der Schleife. Hier ist ein einfaches Beispiel für die Referenz:

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() 

Im Beispiel ist die Funktion sys.stdin.readline() in einem anderen Thread durch die loop.run_in_executor Methode aufgerufen wird. Der Thread bleibt blockiert, bis stdin einen Zeilenvorschub erhält, in der Zwischenzeit ist die Schleife frei, um andere Korutinen auszuführen, wenn sie existierten.