I'm playing a bit with python's asyncio library, in the wake of this example, I wrote the following scripts:
# file: get_rand.py
from random import choice
from time import sleep
import sys
def main():
sys.stderr.write('child: starting loop...\n')
for _ in range(5):
print(choice('abcdefghijklmnopqrstuvwxyz'))
sys.stderr.write('child: going to sleep\n')
sleep(0.5)
if __name__ == '__main__':
main()
and:
# file: async_test.py
import asyncio
import time
class Protocol(asyncio.SubprocessProtocol):
def __init__(self, exit_f):
self.exit = exit_f
print('Protocol initialised')
def pipe_data_received(self, fd, data):
print('Data received')
if fd == 1:
with open('rand_file.txt', 'a') as out:
out.write(bytes(data).decode('ascii'))
elif fd == 2:
print('Received error data!')
print(data)
def pipe_connection_lost(self, fd, exc):
print('Pipe connection lost')
if exc is not None:
print(exc)
raise exc
def process_exited(self):
self.exit.set_result(True)
print('Subprocess exited')
@asyncio.coroutine
def mycoro():
loop = asyncio.get_event_loop()
exit_future = asyncio.Future(loop=loop)
print('creating process...')
subprocess = loop.subprocess_exec(lambda: Protocol(exit_future),
'python3.5', 'get_rand.py',
stdin=None, stderr=None)
transp, proto = yield from subprocess
print('waiting for subprocess to finish...')
yield from exit_future
transp.close()
def main():
loop = asyncio.get_event_loop()
loop.run_until_complete(mycoro())
loop.close()
When executing this code, I get the following:
$ python3.5 async_test.py
creating process...
Protocol initialised
waiting for subprocess to finish...
child: starting loop...
child: going to sleep
child: going to sleep
child: going to sleep
child: going to sleep
child: going to sleep
Data received
Pipe connection lost
Subprocess exited
I have many questions about all this:
- Apparently the data the child sends trigger the pipe_data_received event only once and after the child has terminated. Is there a way to spawn a child process and have the pipe_data_received event triggered at every write on stdout?
- If I remove the line
transp, proto = yield from subprocess
the whole thing just hangs oncreating process...
, so it looks like the child is not started until the parent doestransp, proto = yield from subprocess
. Is that correct? Why is that? - What if I wanted my process to spawn a child which runs forever and periodically triggers the pipe_data_received, while the lauching process keeps its execution flow, and does other stuff? Is this the right tool for such a need?