【发布时间】:2013-04-12 01:11:19
【问题描述】:
我正在尝试与real time subprocess.Popen via stdout and PIPE 非常相似的东西
但是,我也想将输入发送到正在运行的进程。
如果我使用
在单独的线程中启动一个进程process = subprocess.Popen(cmd,stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
我可以使用终端发送输入。
如何从其他来源发送输入,例如不在线程中的单独函数?
我无法使用Popen.communicate,因为我正在尝试与程序进行实时交互,因此正在运行的进程永远不会结束。
提前致谢。
这是我的完整代码,我希望在单击发送按钮时将输入发送到子进程。
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(),你真的尝试过吗?当你这样做时会发生什么? -
@LieRyan:
communicatewaits 让孩子完成并阅读其所有输出。由于“正在运行的进程永远不会结束”,这意味着communicate永远不会返回。所以他不能使用它。 -
您不应该直接从后台线程调用 GUI(它可能会或可能不会间歇性地工作)。您可以使用队列和
root.after()来调度从线程对 GUI 的调用。避免不必要地使用global,您可以使用实例变量,例如self.prompt。您可以使用socket、select模块而不是运行netcat。 -
@J.F.Sebastian:关于直接使用套接字而不是编写脚本
netcat的好处。 (您可能仍然需要一个单独的线程来为该套接字提供服务……但比 3-4 个线程更好地为子进程提供服务……而且要简单得多。它可以在使用 BSD 或 Hobbit netcat 而不是 GNU netcat 的系统上工作,或者根本没有 netcat。等等。)