I am attempting something very similar to real time subprocess.Popen via stdout and PIPE
I, however, want to send input to the running process as well.
If I start a process in a separate thread using
process = subprocess.Popen(cmd,stdout=subprocess.PIPE, stderr=subprocess.STDOUT) I can send input using the terminal.
How would I send input from another source such as separate function not in the thread?
I cannot use Popen.communicate as the running process will never finish, as I am attempting real time interaction with the program.
Thanks in advance.
Here is my complete code, I am looking to have input sent to the subprocoess process when the send button is clicked.
from Tkinter import *` from ttk import *` import subprocess from threading import Thread class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.parent.title("Test Client") self.style = Style() self.style.theme_use("default") self.pack(fill=BOTH, expand=1) #Label, doesnt change lbl = Label(self, text="Client:") lbl.grid(row=0, column=1, sticky=W ) #when output from client is shown global display display = Text(self,width=50,height=20) display.grid(row=1, column=1, sticky=E+W+N+S) #where user input is taken global prompt prompt = Entry(self,width=50) prompt.grid(row=3, column=1, sticky=E+W+N+S) #Button that will send input to client send = Button(self,text="Send",command=self.send) send.grid(row=3, column=2, sticky=N) get = Button(self,text="Get",command=self.get) get.grid(row=2, column=2, sticky=S) def get(self): print foo def send(self): sent = prompt.get() def MyThread(): global sent sent = 2 cmd = ['nc', '-l', '-p', '50000'] process = subprocess.Popen(cmd,stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while True: out = process.stdout.read(1) if out == '' and process.poll() != None: break if out != '': display.insert(INSERT, out) sys.stdout.write(out) sys.stdout.flush() def main(): root = Tk() root.geometry("500x410+300+300") app = Example(root) thread = Thread(target = MyThread, args=()) thread.start() root.mainloop() if __name__ == '__main__': main()
Popen.communicate()for that, have you actually tried it? What happen when you do?communicatewaits for the child to finish and reads all of its output. Since "the running process will never finish", this meanscommunicatewill never return. So he can't use it.root.after()to scheduler a call to GUI from the thread. Avoid usingglobalunnecessarily, you could use instance variables instead e.g.,self.prompt. You could usesocket,selectmodules instead of runningnetcat.netcat. (You'll probably still need a separate thread to service that socket… but better than 3-4 threads to service a subprocess… And a whole lot simpler. And it'll work on systems with BSD or Hobbit netcat instead of GNU netcat, or with no netcat at all. And so on.)