After having experimented a little more, I think I have a working solution, 
but it requires one line change concerning character devices again.
The stream class didn't work out, because of it requires the input and 
output to be on the same file object, what is not possible anymore in 
Python 3. My solution is to connect_read_pipe.

I know that connect_read/write_pipe was not meant to be used for stdin or 
stdout. But they work really very well here and I don't think there is any 
reason not to allow this usage.


class InputProtocol:
    def data_received(self, data):
        pass # Handle input here

output_transport, output_protocol = yield from 
loop.connect_write_pipe(BaseProtocol, os.fdopen(0, 'w'))
input_transport, input_protocol = yield from 
loop.connect_read_pipe(InputProtocol, sys.stdin)

# Print output
output_transport.write(b'output bytes')


For unix_events._UnixReadPipeTransport, it works. Currently, line 196 in 
that file, we have.

        if not (stat.S_ISFIFO(mode) or
                stat.S_ISSOCK(mode) or
                stat.S_ISCHR(mode)):
            raise ValueError("Pipe transport is for pipes/sockets only.")


In unix_events._UnixWritePipeTransport, on the other hand, we have:

        is_socket = stat.S_ISSOCK(mode)
        is_pipe = stat.S_ISFIFO(mode)
        if not (is_socket or is_pipe):
            raise ValueError("Pipe transport is for pipes/sockets only.")

Probably it's a bug that we don't allow character devices there. Shall I go 
ahead and try to create a patch?


Jonathan



Le vendredi 17 janvier 2014 13:59:15 UTC+1, Jonathan Slenders a écrit :
>
> Hi all,
>
> Still trying here to use stdin/stdout in the event loop.
>
> Guido told me to try using StreamReader and StreamWriter from streams.py. 
> This is nice, but I stumbled upon another problem.
>
> The idea is that stdin and stdout are actually exactly the same file. If 
> you make one of those non-blocking, the other becomes non blocking as well.
> The following proves exactly that they are the same.
>
> >>> import os, sys
> >>> o2 = os.fdopen(sys.stdin.fileno(), 'w')
> >>> o2.write('hello\n')
> hello
> 6
> >>>
>
> As far as I understand, in order to use StreamReader/Writer, we need to 
> have one pipe that supports both read and write operations. The 
> StreamReaderProtocol creates an instance of StreamWriter inside its 
> connection_made, using the same transport.
>
> In Python2.7.3, this would be easy. I could do this:
>
> >>> import os
> >>> fd = os.fdopen(0, 'r+')
> >>> 
>
> However, in Python 3.3, I 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.
> >>> 
>
>
> My idea was to do this:
>
>
> def connected_cb(reader, writer):
>     pass
>
> def factory():
>    reader = StreamReader()
>     protocol = StreamReaderProtocol(reader, connected_cb)
>     return protocol
>
> in_and_out = os.fdopen(0, 'r+')
> yield from loop.connect_read_pipe(factory, in_and_out)
>
>
> However, that doesn't work in Python 3.3 because of the 
> UnsupportedOperation error.
> Maybe, I will find a workaround to still be able to use the 
> StreamReader/Writer. But right now, I'm not sure whether even this is the 
> right approach. 
>
> One other question about StreamReaderProtocol.
> Why is it that we pass in stream_reader, but do we create stream_writer in 
> the connection_made. Can't we create both the reader and writer instance in 
> the connection_made? I don't understand this asymmetry.
>
>
> Cheers,
>
> Jonathan
>

Reply via email to