python / asyncio

asyncio historical repository
https://docs.python.org/3/library/asyncio.html
1.05k stars 178 forks source link

Implement async input() #213

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Currently, asyncio doesn't provide any helper to read asynchronously data from 
sys.stdin, like input(). Twisted implements twisted.internet.stdio:

https://twistedmatrix.com/trac/browser/trunk/twisted/internet/stdio.py
https://twistedmatrix.com/trac/browser/trunk/twisted/internet/_posixstdio.py
https://twistedmatrix.com/trac/browser/trunk/twisted/internet/process.py#L106
https://twistedmatrix.com/trac/browser/trunk/twisted/internet/_win32stdio.py

See also https://code.google.com/p/tulip/issues/detail?id=147

Original issue reported on code.google.com by victor.s...@gmail.com on 2 Nov 2014 at 10:55

GoogleCodeExporter commented 9 years ago
Hi,

This seems suspiciously similar to BaseSubprocessTransport and 
SubprocessProtocol. It seems like it could be implemented in a very similar 
matter using sys.stdin and sys.stdout. Thoughts?

Original comment by elizab...@sporksmoo.net on 17 Nov 2014 at 9:19

ghost commented 8 years ago

You can use loop.add_reader(fd, cb) and add a callback function to stdin file descriptor and change tty settings to cbreak. Or you can make a coroutine to read from curses screen getch method with nodelay option. I'm sure there is a more robust/complicated way to this, maybe including StreamReader.

vxgmichel commented 8 years ago

I implemented something similar as part of this project. It provides the following coroutines:

Everything is implemented in stream.py. It should work even if sys.stdin and sys.stdout don't have a file descriptor (inside IDLE for instance).

socketpair commented 8 years ago

https://gist.github.com/nathan-hoad/8966377 - is it good ? @vxgmichel

socketpair commented 8 years ago

I'm vote on implementing stream wrappers for generic file objects.

Something like simple and stupid

vxgmichel commented 8 years ago

@socketpair There are a few differences between the example in your link and the way I wrote it:

About the wrappers you described, I'm not sure it's a good idea to create high level streams from low level objects (file objets, descriptors, sockets). For instance, in order to open a new socket connection, you can either use:

Same thing for subprocesses:

So I would expect file streams to work the same:

socketpair commented 8 years ago

@vxgmichel unfortunatelly, there are cases where file descriptor is pre-exist. For example, systemd's socket activation, or xinetd.

Also, if stdout/stdin is pipe, input and output may block easily, so wrapping them to asyncio stream is convenient.

nhoad commented 7 years ago

FWIW an issue with my gist is that it will break print() calls for sufficiently large output, because stdout is... surprise surprise, non-blocking. Even if you decide to only have a non-blocking stdin you'll hit issues, because stdin and stdout are actually the same object for TTYs, as per this issue: https://github.com/python/asyncio/issues/147.

Also, os.fdopen(1, 'wb') and sys.stdout are interchangeable and there's no reason to use one over the other.