2015-07-20 11 views
11

Próbuję odczytać stdin asynchronicznie na Windows 7 64-bit i Python 3.4.3aysncio nie może odczytać stdin na Windows

Próbowałem ten zainspirowany 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() 

Jednakże, podnosi OSError: [WInError 100381] An operation was attempted on something that is not a socket.

Czy obiekt podobny do pliku, taki jak stdin, może zostać zawinięty w klasę, aby nadać mu interfejs API gniazda? Mam asked this question separately, ale jeśli rozwiązanie jest proste, odpowiedz tutaj.

Zakładając, że nie mogę zawinąć obiekt plikopodobny aby to gniazdo, próbowałem za pomocą strumieni jako inspirowane przez 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() 

A to rodzi NotImplementedError w asyncio.base_events._make_read_pipe_transport

Proszę doradzić, w jaki sposób do odczytu stdin przy użyciu na Windows ...

Odpowiedz

10

Wyjątek NotImplementedError został podniesiony, ponieważ nie są su pportowane przez SelectorEventLoop, która jest domyślną pętlą zdarzeń ustawioną na asyncio. Aby obsługiwać rury w systemie Windows, musisz użyć urządzenia ProactorEventLoop. Jednak nadal nie będzie działać, ponieważ funkcje connect_read_pipe i connect_write_pipe nie obsługują stdin/stdout/stderr ani plików w systemie Windows jako Python 3.5.1.

Jednym ze sposobów odczytu z stdin z zachowaniem asynchronicznym jest użycie wątku z metodą pętli o nazwie run_in_executor. Jest prosty przykład w celach:

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

W tym przykładzie funkcja sys.stdin.readline() nazywa się w innym wątku metodą loop.run_in_executor. Wątek pozostaje zablokowany do momentu, aż stdin odbierze linię, w międzyczasie pętla może wykonywać inne współprogramy, jeśli istniały.

Powiązane problemy