I am running a simple server on windows and outputting the process to a simple GUI.
I want to keep this process running, but execute other simple processes in the same terminal.
When I try to write any further processes to the terminal the UI freezes, although the server continues to run, the command itself is not executed on the server.
I have a simple batch process to simulate the server that executes every 5 seconds
#runserver.bat
:loop
@echo OFF
@echo %time%
ping localhost -n 6 > nul
goto loop
The output will run indefinitely once called until the script is terminated even when the UI locks up.
from threading import Thread
from subprocess import Popen, PIPE, STDOUT, call
from Tkinter import *
from ttk import Frame, Button, Label, Style
from Queue import Queue, Empty
from collections import deque
from itertools import islice
def iter_except(function, exception):
try:
while True:
yield function()
except exception:
return
class buildGUI(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.proc = Popen("runserver.bat", shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
q = Queue()
t = Thread(target=self.reader_thread, args=[q]).start()
#setup UI
self.parent.title("Server Manager")
self.style = Style()
self.style.theme_use("default")
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(7, weight=1)
self.rowconfigure(5, pad=2)
self.loglbl = Label(self, text="Log")
self.loglbl.grid(sticky=W, column=1, pady=4, padx=5)
self.var = StringVar()
self.playerlbl = Label(self, text=0, textvariable=self.var)
self.playerlbl.grid(sticky=W, column=0, row=5, pady=4, padx=5)
self.area = Text(self)
self.area.grid(row=1, column=1, columnspan=2, rowspan=10,
padx=5, sticky=E+W+S+N)
self.dirbtn = Button(self, text="dir")
self.dirbtn.grid(row=3, column=0,pady=4, padx=5)
self.dirbtn.bind("<Button-1>", self.runProcess)
self.updateUI(q)
def runProcess(self, event):
print "pressed"
self.proc.communicate("dir")
def reader_thread(self, q):
#add output to thread
for line in iter(self.proc.stdout.readline, b''):
q.put(line)
def updateUI(self, q):
#use deque to discard lines as they are printed to the UI,
for line in deque(islice(iter_except(q.get_nowait, Empty), None), maxlen=5):
if line is None:
return # stop updating
else:
self.area.insert(END,line) # update GUI
self.parent.after(1000, self.updateUI, q) # schedule next update
def main():
root = Tk()
root.geometry("850x450+100+100")
app = buildGUI(root)
root.mainloop()
if __name__ == '__main__':
main()
I have tried replacing communicate()
with stdin.write
but both lock up the UI
def runProcess(self, event):
print "pressed"
self.proc.communicate("dir")
I haven't been able to find any examples where someone needed to execute a process during an existing process, most examples assume that a process can either be terminated or the process can be executed when the other is finished, so a poll or terminate can be used.
The only example that reads with an open process appears to terminate the process. [answer/(https://stackoverflow.com/a/16770371)
I have tried calling additional Popen commands, but this just appears to be ignored by the server