import asyncio
import sys
from asyncio.unix_events import _set_nonblocking
from asyncio.streams import StreamWriter
EVENT_LOOP = asyncio.get_event_loop()
@asyncio.coroutine
def stdio(stdin=sys.stdin, stdout=sys.stdout):
class Stdout(asyncio.Protocol): pass # unused, just a placeholder
_set_nonblocking(stdin.fileno())
_set_nonblocking(stdout.fileno())
reader = asyncio.StreamReader()
reader_protocol = asyncio.StreamReaderProtocol(reader)
yield from EVENT_LOOP.connect_read_pipe(lambda: reader_protocol, stdin)
transport, protocol = yield from EVENT_LOOP.connect_write_pipe(Stdout, stdout)
writer = StreamWriter(transport, protocol, reader, EVENT_LOOP)
while True:
# toggle these two assignments to line to see stdout working vs not
# line = b'test line\n'
line = yield from reader.readline()
print(line, file=sys.stderr)
writer.write(b'data received ')
writer.write(line)
EVENT_LOOP.run_until_complete(stdio())
nathan@nathan $ python asyncio
1
b'1\n'
2
b'2\n'
3
b'3\n'
pipe closed by peer or os.write(pipe, data) raised exception.
4
b'4\n'
pipe closed by peer or os.write(pipe, data) raised exception.
pipe closed by peer or os.write(pipe, data) raised exception.
5
b'5\n'
pipe closed by peer or os.write(pipe, data) raised exception.
pipe closed by peer or os.write(pipe, data) raised exception.
nathan@nathan $ python asyncio
b'test line\n'
data received test line
b'test line\n'
data received test line
b'test line\n'
data received test line
b'test line\n'
data received test line
b'test line\n'
data received test line
b'test line\n'
data received test line
b'test line\n'
data received test line
b'test line\n'
data received test line
b'test line\n'
data received test line
b'test line\n'
data received test line
output_transport, output_protocol = yield from loop.connect_write_pipe(BaseProtocol, os.fdopen(0, 'wb'))
input_transport, input_protocol = yield from loop.connect_read_pipe(
lambda:OurInputProtocol(session), sys.stdin)
Not sure whether that's the best way.
See the example in https://github.com/jonathanslenders/libpymux and take a look at https://github.com/jonathanslenders/pymux
>>> 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.
>>>
Ah, clever. It needs a little more research--is it always the case that a tty FD works this way? But tentatively worth getting into RC2.
I'm not sure that I understand correctly. stdin are stdout have a
different file descriptor: 0 and 1. But in case of PTY, it looks like
0 and 1 are the same file: os.path.samestat(os.fstat(0), os.fstat(1))
is True.
It looks like writing data into the PTY raises a read
event, and os.read() on the file descriptor returns the written data.
Le mercredi 19 février 2014 17:32:25 UTC+1, Victor Stinner a écrit :I'm not sure that I understand correctly. stdin are stdout have a
different file descriptor: 0 and 1. But in case of PTY, it looks like
0 and 1 are the same file: os.path.samestat(os.fstat(0), os.fstat(1))
is True.This is because the file descriptor is copied, this is how forkpty works.
Maybe you can take a look at this line of pexpect:
It looks like writing data into the PTY raises a read
event, and os.read() on the file descriptor returns the written data.This is only the case when the pty is in canonical mode. (The pty implements some line editing/buffering functionality itself.)
Maybe you want to set the pty in raw mode first. Everything seems more logical then:
To the questions considering asyncio itself, I don't have a real answer.