I want to be able to programmatically run a file, arbitrarily give it inputs (stdin) at any time, and periodically poll for any stdout. I also want to be able to kill the process whenever I want.
Here's what I have tried:
import subprocess
from threading import Thread
class Runner:
def __init__(self):
self.process = subprocess.Popen(
["python", "x.py"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
def run(self):
self.process.wait()
def poll(self):
print("got stdout:", self.process.stdout.readline().decode(), end="")
def give_input(self, text=""):
return self.process.stdin.write(bytes(text))
def kill(self):
self.process.kill()
r = Runner()
t = Thread(target=r.run)
t.start()
r.poll() # should be "hi"
r.poll() # should be "your name:"
r.give_input("hi\n")
r.kill()
t.join()
Here's the code in x.py
print("hi")
input("Your name: ")
So in my demo, I start a thread that will call run which will run the process. Then, I poll for stdout twice. It should print
got stdout: hi
got stdout: Your name:
Afterwards, I give an stdin to the process -- hi\n.
At this point, the program should terminate, and I make sure of it by doing r.kill().
However, the program does not work as expected.
Instead, the program freezes at the second r.poll(), and I'm not sure why. I suspect that since there is no newline, the program will keep reading, but I'm not sure how to prevent it from doing this.
Any ideas?
Here's what I finally came up with, (with code from a non blocking read on
subprocess.PIPE:Unfortunately, I was not able to figure out how to interactively give
stdinto the process, nor was I able to periodically poll forstdout, but I was able to figure out a decent solution for my use case. Instead of getting output every so often, I instead just ran it for a few seconds before terminating the program.