Skip to content

Instantly share code, notes, and snippets.

@leonmax
Last active May 14, 2024 19:58
Show Gist options
  • Save leonmax/16e1fc216b8c36bc2c23 to your computer and use it in GitHub Desktop.
Save leonmax/16e1fc216b8c36bc2c23 to your computer and use it in GitHub Desktop.
sample to run subprocess and log stdout/stderr with asyncio
__author__ = 'leonmax'
import asyncio
from asyncio import (coroutine, subprocess)
import sys
import logging
FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
logging.basicConfig(level=logging.INFO, format=FORMAT)
@coroutine
def log_stream(level, stream):
while not stream.at_eof():
data = yield from stream.readline()
line = data.decode('ascii').rstrip()
logging.log(level, line)
@coroutine
def execute(command, *argument):
proc = yield from asyncio.create_subprocess_exec(command, *argument,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
tasks = [asyncio.async(log_stream(logging.INFO, proc.stdout)),
asyncio.async(log_stream(logging.ERROR, proc.stderr)),
asyncio.async(proc.wait())]
yield from asyncio.wait(tasks)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(execute(sys.executable, *sys.argv[1:]))
loop.close()

run subproc.py from exec.py and capture its stdout/stderr, good for writing a wrapper script

just run the following:

python exec.py subproc.py 10
__author__ = 'leonmax'
from asyncio import coroutine, sleep, get_event_loop
import sys
@coroutine
def run(times):
for i in range(times):
print("trust me ", i)
yield from sleep(1)
print("I blew it", file=sys.stderr)
yield from sleep(1)
if __name__ == "__main__":
loop = get_event_loop()
times = int(sys.argv[1]) if len(sys.argv) > 1 else 10
loop.run_until_complete(run(times))
loop.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment