在连续批处理进程python中执行第二个进程

时间:2015-01-15 23:23:19

标签: python python-2.7 subprocess popen

我在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命令,但这似乎被服务器忽略了

1 个答案:

答案 0 :(得分:0)

要在不阻止GUI的情况下运行第二个进程,请以与第一个进程相同的方式在中完全启动第二个线程。

如果您不需要“实时”捕获输出,那么代码可能更简单:只需在另一个线程中调用subprocess.call()proc.communicate()

如果您根本不需要捕获输出,那么可以使用不会长时间阻塞的Popen()来启动子进程。