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.)