我在Windows上运行一个简单的服务器,并将流程输出到一个简单的GUI。
我想让这个过程继续运行,但是在同一个终端中执行其他简单的过程。
当我尝试将任何进一步的进程写入终端时,UI冻结,尽管服务器继续运行,但命令本身并未在服务器上执行。
我有一个简单的批处理过程来模拟每5秒执行一次的服务器
#runserver.bat
:loop
@echo OFF
@echo %time%
ping localhost -n 6 > nul
goto loop
一旦调用,输出将无限期地运行,直到脚本终止时脚本终止。
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()
我尝试用communicate()
替换stdin.write
,但都锁定了用户界面
def runProcess(self, event):
print "pressed"
self.proc.communicate("dir")
我无法找到任何需要在现有流程中执行流程的示例,大多数示例假设流程可以终止,或者流程可以在另一个流程完成时执行,因此进行调查或终止可以使用。
使用开放进程读取的唯一示例似乎终止进程。 [答案/(https://stackoverflow.com/a/16770371)
我尝试过调用其他Popen命令,但这似乎被服务器忽略了
答案 0 :(得分:0)
要在不阻止GUI的情况下运行第二个进程,请以与第一个进程相同的方式在中完全启动第二个线程。
如果您不需要“实时”捕获输出,那么代码可能更简单:只需在另一个线程中调用subprocess.call()
或proc.communicate()
。
如果您根本不需要捕获输出,那么可以使用不会长时间阻塞的Popen()
来启动子进程。