Last active
October 14, 2022 07:57
-
-
Save ateska/ed4630fef2a1617ae2c44f87b8f0f84e to your computer and use it in GitHub Desktop.
Simultaneously read stdout and stderr from Python `asyncio` create_subprocess_exec
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
async def run(): | |
proc = await asyncio.create_subprocess_exec( | |
'/bin/ls', '/etc', '/not-exists', | |
stdout=asyncio.subprocess.PIPE, | |
stderr=asyncio.subprocess.PIPE | |
) | |
# Prepare set of asynchronous readline() tasks for `stdout` and `stderr` streams | |
aws = { | |
asyncio.create_task(proc.stdout.readline(), name="stdout"), | |
asyncio.create_task(proc.stderr.readline(), name="stderr"), | |
} | |
while len(aws) > 0: | |
done, aws = await asyncio.wait(aws, return_when=asyncio.FIRST_COMPLETED) | |
for task in done: | |
line = await task | |
# If the line is empty, we are at the end of the stream | |
if len(line) == 0: | |
continue | |
print(">>", task.get_name(), line) | |
# Re-create a readline() task for a respective stream | |
if task.get_name() == "stdout": | |
aws.add(asyncio.create_task(proc.stdout.readline(), name="stdout")) | |
elif task.get_name() == "stderr": | |
aws.add(asyncio.create_task(proc.stderr.readline(), name="stderr")) | |
# Wait till the process is finished | |
returncode = await proc.wait() | |
print('Exited with code', returncode) | |
asyncio.run(run()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment