Hello Jonathan, The snippet you've sent through has worked perfectly for me, thank you. I found the os.fdopen(0, 'wb') call was important, as was the order - connecting the read pipe before the write pipe resulted in silence.
Thank you for the explanation on stdin/stdout in a pseudo terminal - that helped make more sense of it all to me. What follows is a rough example of asynchronous stdin/stdout, implemented as an async version of input(). Hopefully this will be of use to someone in the future. As a bonus, the os.fdopen() call means that regular print() calls will still work. import os import asyncio import sys from asyncio.streams import StreamWriter, FlowControlMixin reader, writer = None, None @asyncio.coroutine def stdio(loop=None): if loop is None: loop = asyncio.get_event_loop() reader = asyncio.StreamReader() reader_protocol = asyncio.StreamReaderProtocol(reader) writer_transport, writer_protocol = yield from loop.connect_write_pipe(FlowControlMixin, os.fdopen(0, 'wb')) writer = StreamWriter(writer_transport, writer_protocol, None, loop) yield from loop.connect_read_pipe(lambda: reader_protocol, sys.stdin) return reader, writer @asyncio.coroutine def async_input(message): if isinstance(message, str): message = message.encode('utf8') global reader, writer if (reader, writer) == (None, None): reader, writer = yield from stdio() writer.write(message) line = yield from reader.readline() return line.decode('utf8').strip() @asyncio.coroutine def main(): name = yield from async_input("What's your name? ") print("Hello, {}!".format(name)) asyncio.get_event_loop().run_until_complete(main()) Thank you, Nathan. On Thu, Feb 13, 2014 at 12:02 AM, Jonathan Slenders <jonathan.slend...@gmail.com> wrote: > One thing that could be also confusing is that (as far as I understand) > stdin and stdout are actually the same file if your process is attached to a > pseudo terminal. In that case, stdin is opened as read, while stdout is > opened as write. (Internally, often os.dup2 is used by the parent process to > copy the file descriptor from '0' to '1' and '2' before running exec, making > them identical. See pexpect for instance.) But if you open a subprocess, > it's possible to use pipes, and I think in that case, they are really > different file descriptors. > > Further. > StreamReader and StreamWriter are often used in pairs. In Python2.7.3, you > can do create a bidirectional pipe on stdin/out as follows: > >>>> import os >>>> fd = os.fdopen(0, 'r+') >>>> > > Now 'fd' supports both read and write operations. > However, in Python 3.3, you can't create such an object: > >>>> import os >>>> os.fdopen(0, 'r+') > > > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "/usr/lib/python3.3/os.py", line 1032, in fdopen > return io.open(fd, *args, **kwargs) > io.UnsupportedOperation: File or stream is not seekable. >>>> > > > I think that could be a bug in Python 3, but I'm not sure. >