python - 如果我想在处理过程中看到时钟图标怎么办?
问题描述
如果我想在处理过程中看到时钟图标怎么办?
def refresh():
window.config(cursor="clock")
p = subprocess.Popen("ping 8.8.8.8 -c 3", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while p.stdout is not None:
line = p.stdout.readline()
# Add line in list and remove carriage return
if not line:
p.stdout.flush()
break
text.insert(INSERT, "test\n")
btn_refresh = Button(frame2, text="Refresh Data", command=refresh)
解决方案
尝试这个:
from subprocess import Popen, PIPE
from threading import Thread, Lock
import tkinter as tk
# Global variables
proc = None
running = True
stdout_buffer = ""
stdout_buffer_lock = Lock()
def stdout_loop():
global stdout_buffer
with stdout_buffer_lock:
# Get the data and clear the buffer:
data, stdout_buffer = stdout_buffer, ""
text.config(state="normal")
text.insert("end", data)
text.see("end")
text.config(state="disabled")
if proc is None:
if len(commands) == 0:
# If we are done with all of the commands:
text.config(cursor="")
root.config(cursor="")
else:
# If we have more commands to do call `start_next_proc`
start_next_proc()
else:
root.after(100, stdout_loop)
def start_next_proc():
global proc, commands
command = commands.pop(0) # Take the first one from the list
proc = Popen(command, shell=True, stdout=PIPE)
new_thread = Thread(target=read_stdout, daemon=True)
new_thread.start()
stdout_loop()
def start_new_proc():
global commands
# For linux use "-c 5". For windows use "-n 5"
commands = ["ping 8.8.8.8 -c 5",
"ping 1.1.1.1 -c 5",
"ping 5.5.5.5 -c 5"]
start_next_proc()
text.config(cursor="clock")
root.config(cursor="clock")
def read_stdout():
global proc, stdout_buffer
while proc.poll() is None:
line = proc.stdout.readline()
with stdout_buffer_lock:
stdout_buffer += line.decode()
proc = None
root = tk.Tk()
text = tk.Text(root, state="disabled")
text.pack()
button = tk.Button(root, text="Run", command=start_new_proc)
button.pack()
root.mainloop()
在代码中,我在主线程中启动进程,然后启动 2 个循环。其中一个循环是while
内部的循环read_stdout
。它从进程中读取所有数据并将其写入stdout_buffer
. 第二个循环是一个tkinter
循环(在 stdout_loop 内),它在小部件stdout_buffer
内读取和写入它Text
。
我还使用锁来确保缓冲区不会被破坏。
如果tkinter
是线程安全的,那么代码会短得多,但事实并非如此。
如果你想要它作为一个类:
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) -> 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:
super().config(cursor="")
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, shell=True, 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()
super().config(cursor="clock")
def read_stdout(self):
while self.proc.poll() is None:
line = self.proc.stdout.readline()
with self.stdout_buffer_lock:
self.stdout_buffer += line.decode()
self.proc = None
if __name__ == "__main__":
def start_commands():
# For linux use "-c 5". For windows use "-n 5"
commands = ["echo hi",
"ping 1.1.1.1 -n 3",
"ping 5.5.5.5 -n 3"]
tkinter_popen.run_commands(commands)
root = tk.Tk()
tkinter_popen = TkinterPopen(root)
tkinter_popen.pack()
button = tk.Button(root, text="Run", command=start_commands)
button.pack()
root.mainloop()
推荐阅读
- reactjs - this.props 反应训练问题 - CodeAcademy
- java - Java String 对象相等和引用
- javascript - 我们可以从 javascript 文件发送 ajax 吗?
- spring-boot - spring-ws - Oracle Weblogic 12c
- java - 如何使用 JAXB 设置抽象类的集合以在 Jackson 中进行反序列化?
- listview - 扑。如何将行的第一个孩子扩展到列表视图高度作为第二个孩子?
- kubernetes - 有没有办法从文件创建的 configmap 在 pod 中配置环境变量?
- html - 使用 Bootstrap 4 导航栏组织 HTML 网站
- flutter - 如何在列表中保存共享偏好?
- python - 在多终端中打开 Python 函数