<p>试试这个:</p>
<pre class="lang-py prettyprint-override"><code>from subprocess import Popen, PIPE
from threading import Thread, Lock
import tkinter as tk
class TkinterPopen(tk.Text):
def __init__(self, master, state="disabled", **kwargs):
super().__init__(master, state=state, **kwargs)
self.commands = []
self.proc = None
self.running = True
self.stdout_buffer = ""
self.stdout_buffer_lock = Lock()
def stdout_loop(self, last_loop:bool=False) -> None:
with self.stdout_buffer_lock:
# Get the data and clear the buffer:
data, self.stdout_buffer = self.stdout_buffer, ""
state = super().cget("state")
super().config(state="normal")
super().insert("end", data)
super().see("end")
super().config(state=state)
if self.proc is None:
if len(self.commands) == 0:
# If we are done with all of the commands:
if last_loop:
return None
super().after(100, self.stdout_loop, True)
else:
# If we have more commands to do call `start_next_proc`
self.start_next_proc()
else:
super().after(100, self.stdout_loop)
def start_next_proc(self) -> None:
command = self.commands.pop(0) # Take the first one from the list
self.proc = Popen(command, stdout=PIPE)
new_thread = Thread(target=self.read_stdout, daemon=True)
new_thread.start()
self.stdout_loop()
def run_commands(self, commands:list) -> None:
self.commands = commands
self.start_next_proc()
def read_stdout(self):
while self.proc.poll() is None:
self._read_stdout()
self._read_stdout()
self.proc = None
def _read_stdout(self) -> None:
line = self.proc.stdout.readline()
with self.stdout_buffer_lock:
self.stdout_buffer += line.decode()
if __name__ == "__main__":
def start_echo():
command = ["echo", "hi"]
tkinter_popen.run_commands([command])
def start_ping():
# For linux use "-c". For windows use "-n"
command = ["ping", "1.1.1.1", "-n", "3"]
tkinter_popen.run_commands([command])
root = tk.Tk()
tkinter_popen = TkinterPopen(root)
tkinter_popen.pack()
button = tk.Button(root, text="Run echo", command=start_echo)
button.pack()
button = tk.Button(root, text="Run ping", command=start_ping)
button.pack()
root.mainloop()
</code></pre>
<p>我想这就是你想要的功能。代码类似于@acw1668,但我在另一个线程中读取了<code>stdout</code>,并在名为<code>self.stdout_buffer</code>的队列中取出了数据</p>
<p>这只是我给出的答案的副本</p>