I have stuck with a pretty simple problem - I can't communicate with process' stdout. The process is a simple stopwatch, so I'd be able to start it, stop and get current time.
The code of stopwatch is:
import argparse
import time
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument('start', type=int, default=0)
start = parser.parse_args().start
while True:
print(start)
start += 1
time.sleep(1)
if __name__ == "__main__":
main()
And its manager is:
import asyncio
class RobotManager:
def __init__(self):
self.cmd = ["python", "stopwatch.py", "10"]
self.robot = None
async def start(self):
self.robot = await asyncio.create_subprocess_exec(
*self.cmd,
stdout=asyncio.subprocess.PIPE,
)
async def stop(self):
if self.robot:
self.robot.kill()
stdout = await self.robot.stdout.readline()
print(stdout)
await self.robot.wait()
self.robot = None
async def main():
robot = RobotManager()
await robot.start()
await asyncio.sleep(3)
await robot.stop()
await robot.start()
await asyncio.sleep(3)
await robot.stop()
asyncio.run(main())
But stdout.readline returns an empty byte string every time.
When changing stdout = await self.robot.stdout.readline() to stdout, _ = await self.robot.communicate(), the result is still an empty byte string.
When adding await self.robot.stdout.readline() to the end of the RobotManager.start method, it hangs forever.
However, when removing stdout=asyncio.subprocess.PIPE and all readline calls, the subprocess prints to the terminal as expected.
How do I read from the subprocess stdout correctly?
In this case "proc.communicate" cannot be used; it's not suitable for the purpose, since the OP wants to interrupt a running process. The sample code in the Python docs also shows how to directly read the piped stdout in these cases, so there is in principle nothing wrong with doing that.
The main problem is that the stopwatch process is buffering the output. Try using as command:
["python", "-u", "stopwatch.py", "3"]For debugging it will also help to add some prints indicating when the robot started and ended. The following works for me: