Glad I could help! And yes, we could use more examples...

On Sat, May 17, 2014 at 6:23 PM, Dan McDougall <[email protected]> wrote:

> On Saturday, May 17, 2014 5:43:34 PM UTC-4, Guido van Rossum wrote:
>>
>> The reason the reader/writer don't expose their FD is that there's
>> already a handler registered for them, so registering your own would have
>> disappointing effects.
>>
>
> Ahh, now that makes perfect sense.  I thought I was missing something or
> perhaps someone "just forgot" to add the fileno() method (hehe).  Thank
> you.  I figured there would be a very good reason why it works the way it
> does.
>
> TBH I don't see anything wrong with your first version -- if you don't
>> need the full treatment you shouldn't have to pay for it. :-)
>>
>
> I just wanted to write simpler/easier-to-understand code.  I know that it
> took me a while to grok pty.fork() the first time I used it so I thought it
> would be better to use something more concise like, "yield from
> asyncio.the_one_right_way_to_do_this()" =D
>
> But if you want to use asyncio's create_subprocess_shell() you can just
>> write a coroutine that reads from the reader and prints its output, and run
>> that reader:
>>
>> @asyncio.coroutine
>> def tail(reader):
>>     while True:
>>         data = yield from reader.read(8192)
>>         if not data:
>>             break
>>         # here you print data (note it's a bytes object)
>>
>> @asyncio.coroutine
>> def setup():
>>     reader, writer = yield from asyncio.create_subprocess_shell(......)
>>     yield from tail(reader)
>>
>> asyncio.get_event_loop().run_until_complete(setup())
>>
>> There's also a lower-level subprocess API on the event loop; it lets you
>> write a Protocol subclass; in that class you can write a data_received()
>> method that prints your data:
>>
>> class TailProtocol:
>>      def data_received(self, data):
>>         # here you print data (note it's a bytes object)
>>
>> @asyncio.coroutine
>> def setup():
>>     transport, protocol = yield from loop.subprocess_shell(TailProtocol,
>> program, *args)
>>
>> The termination condition in this case is a little complex, you probably
>> want to create a Future in TailProtocol.__init__() that is made complete by
>> the connection_lost() callback:
>>
>> class TailProtocol:
>>     def __init__(self):
>>         self.complete = asyncio.Future()
>>     def data_received(self, data):
>>         # etc.
>>     def connection_lost(self, err):
>>         self.complete.set_result(err)
>>
>> @asyncio.coroutine
>> def setup():
>>     transport, protocol = yield from loop.subprocess_shell(TailProtocol,
>> program, *args)
>>     yield from protocol.complete
>>
>> asyncio.get_event_loop().run_until_complete(setup())
>>
>> Hope this isn't too overwhelming for you. :-)
>>
>
> Excellent.  I figured there was a way to do it with a Protocol but I'm
> still new to the asyncio package and hadn't crossed that bridge yet (my
> mind is still in "Tornado mode").  Another thing making it tough is the
> fact that asyncio *so new* that there's very little to be found when
> googling for examples.  I'm going to see if I can fix that =D
>
> For reference I'm not actually trying to run 'tail' on a log file...  It's
> all part of some re-plumbing of Gate 
> One<https://github.com/liftoff/GateOne>in order to better support the new 
> web-based
> X11 interface <http://youtu.be/6zJ8TNcWTyo>.  I figured, "If I'm going to
> use asyncio with X11 stuff I might as well get regular ol' web-based
> terminals working with it too."
>



-- 
--Guido van Rossum (python.org/~guido)

Reply via email to