Monitor processes with Python asyncio
Challenge
Use the new Python 3.5 asyncio to asynchronously spawn processes and monitor their status
Prerequisites
Python 3.5
Code
import asyncio
import sys
procs=dict()
@asyncio.coroutine
def start_process():
script = """
import sys
import random
import time
import multiprocessing
proc = multiprocessing.current_process()
wait_range = random.randint(1, 15)
print('proc with id {pid} has a wait_range of {w_range}'.format(pid=str(proc.pid), w_range=str(wait_range)))
for i in range(wait_range):
print('proc with id {pid} and iteration {it}'.format(pid=str(proc.pid), it=str(i)))
time.sleep(1)
sys.exit(random.choice([0, 1]))
"""
# Create the subprocess, redirect the standard output into a pipe
create = asyncio.create_subprocess_exec(sys.executable, '-c', script,
stdout=asyncio.subprocess.PIPE,
bufsize=0)
proc = yield from create
return proc
@asyncio.coroutine
def readline(proc):
data = yield from proc.stdout.readline()
line = data.decode('ascii').rstrip()
return line
@asyncio.coroutine
def monitor_procs(procs):
while True:
yield from asyncio.sleep(1)
for pid, proc in list(procs.items()):
if proc.returncode is None:
print('Proc with id: {pid} still running'.format(pid=pid))
elif proc.returncode is 0:
print('Proc with id: {pid} exited with code 0, removing...'.format(pid=pid))
procs.pop(pid, None)
else:
print('Proc with id: {pid} exited with code {exit_code}, removing...'.format(pid=pid, exit_code=proc.returncode))
procs.pop(pid, None)
@asyncio.coroutine
def generate_process(procs):
while True:
yield from asyncio.sleep(5)
print('Starting new Process...')
proc = yield from start_process()
procs[proc.pid] = proc
@asyncio.coroutine
def follow_procs(procs):
while True:
yield from asyncio.sleep(0.01)
for pid, proc in list(procs.items()):
line = yield from readline(proc)
if line:
print(line)
if sys.platform == "win32":
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
tasks = asyncio.gather(
asyncio.async(monitor_procs(procs)),
asyncio.async(generate_process(procs)),
#asyncio.async(follow_procs(procs))
)
asyncio.get_event_loop().run_forever()
The console output:
Starting new Process...
Proc with id: 64715 still running
Proc with id: 64715 still running
Proc with id: 64715 still running
Proc with id: 64715 still running
Proc with id: 64715 still running
Starting new Process...
Proc with id: 64715 still running
Proc with id: 64731 still running
Proc with id: 64715 still running
Proc with id: 64731 still running
Proc with id: 64715 still running
Proc with id: 64731 still running
Proc with id: 64715 still running
Proc with id: 64731 still running
Proc with id: 64715 exited with code 1, removing...
Proc with id: 64731 still running
Starting new Process...
Proc with id: 64747 still running
Proc with id: 64731 still running
Proc with id: 64747 still running
Proc with id: 64731 still running
Proc with id: 64747 still running
Proc with id: 64731 still running
Proc with id: 64747 still running
Proc with id: 64731 still running
Proc with id: 64747 still running
Proc with id: 64731 still running
Starting new Process...
Proc with id: 64747 still running
Proc with id: 64765 still running
Proc with id: 64731 still running
Proc with id: 64747 still running
Proc with id: 64765 still running
Proc with id: 64731 still running
Proc with id: 64747 still running
Proc with id: 64765 still running
Proc with id: 64731 exited with code 0, removing...