gpt4 book ai didi

python - 运行实时输出到 Tkinter GUI 的进程

转载 作者:太空宇宙 更新时间:2023-11-03 11:27:51 24 4
gpt4 key购买 nike

我试图在 Tkinter python 中创建一个 GUI。我想将工具的输出显示到我的 Tkinter 界面。该工具在命令行中运行良好,但它是一个连续的扫描仪。有点像连续的 ping(我的意思是 Linux 中没有选项的 ping 命令)。

现在的问题是因为 ping 的输出永远不会完成,所以我无法在 Tkinter 中打印输出。它还使我的应用程序卡住。几秒钟后我也无法停止命令以显示输出。 Run process with realtime output in PHP我发现上面的链接对 php 有帮助,但是如何在 python 中转换此代码:

https://stackoverflow.com/a/6144213/4931414

这是我想在 tkinter 框架上显示的一些示例代码

#!/usr....

import subprocess
x = subprocess.call(["ping", "127.0.0.1"])
print x

这在命令行上效果很好,但我在 tkinter 界面上没有得到输出。

最佳答案

首先,我必须承认我对subprocess这个模块不是很熟悉。和 threading ,但我尝试创建一个简单的控制台,让您可以编写命令,其输出将显示在 Text 中。小部件。

基本思想是有一个新的运行并行线程,它在您单击Execute 按钮时处理命令。我们不断迭代 stdout 的行并将它们插入到文本小部件中。

它似乎适用于任何命令,但我很确定存在一些问题和错误。如果你们更熟悉我上面引用的模块,看到我的代码有任何严重的问题,或者有任何改进建议,我一定会听取你们的意见,以改进这个例子。

现在,这是代码:

import tkinter as tk
from tkinter.scrolledtext import ScrolledText
import threading
from subprocess import Popen, PIPE


class Console(tk.Frame):

"""Simple console that can execute bash commands"""

def __init__(self, master, *args, **kwargs):
tk.Frame.__init__(self, master, *args, **kwargs)

self.text_options = {"state": "disabled",
"bg": "black",
"fg": "#08c614",
"insertbackground": "#08c614",
"selectbackground": "#f01c1c"}

self.text = ScrolledText(self, **self.text_options)

# It seems not to work when Text is disabled...
# self.text.bind("<<Modified>>", lambda: self.text.frame.see(tk.END))

self.text.pack(expand=True, fill="both")

# bash command, for example 'ping localhost' or 'pwd'
# that will be executed when "Execute" is pressed
self.command = ""
self.popen = None # will hold a reference to a Popen object
self.running = False # True if the process is running

self.bottom = tk.Frame(self)

self.prompt = tk.Label(self.bottom, text="Enter the command: ")
self.prompt.pack(side="left", fill="x")
self.entry = tk.Entry(self.bottom)
self.entry.bind("<Return>", self.start_thread)
self.entry.bind("<Command-a>", lambda e: self.entry.select_range(0, "end"))
self.entry.bind("<Command-c>", self.clear)
self.entry.focus()
self.entry.pack(side="left", fill="x", expand=True)

self.executer = tk.Button(self.bottom, text="Execute", command=self.start_thread)
self.executer.pack(side="left", padx=5, pady=2)
self.clearer = tk.Button(self.bottom, text="Clear", command=self.clear)
self.clearer.pack(side="left", padx=5, pady=2)
self.stopper = tk.Button(self.bottom, text="Stop", command=self.stop)
self.stopper.pack(side="left", padx=5, pady=2)

self.bottom.pack(side="bottom", fill="both")

def clear_text(self):
"""Clears the Text widget"""
self.text.config(state="normal")
self.text.delete(1.0, "end-1c")
self.text.config(state="disabled")

def clear_entry(self):
"""Clears the Entry command widget"""
self.entry.delete(0, "end")

def clear(self, event=None):
"""Does not stop an eventual running process,
but just clears the Text and Entry widgets."""
self.clear_entry()
self.clear_text()

def show(self, message):
"""Inserts message into the Text wiget"""
self.text.config(state="normal")
self.text.insert("end", message)
self.text.see("end")
self.text.config(state="disabled")

def start_thread(self, event=None):
"""Starts a new thread and calls process"""
self.stop()
self.running = True
self.command = self.entry.get()
# self.process is called by the Thread's run method
threading.Thread(target=self.process).start()

def process(self):
"""Runs in an infinite loop until self.running is False"""
while self.running:
self.execute()

def stop(self):
"""Stops an eventual running process"""
if self.popen:
try:
self.popen.kill()
except ProcessLookupError:
pass
self.running = False

def execute(self):
"""Keeps inserting line by line into self.text
the output of the execution of self.command"""
try:
# self.popen is a Popen object
self.popen = Popen(self.command.split(), stdout=PIPE, bufsize=1)
lines_iterator = iter(self.popen.stdout.readline, b"")

# poll() return None if the process has not terminated
# otherwise poll() returns the process's exit code
while self.popen.poll() is None:
for line in lines_iterator:
self.show(line.decode("utf-8"))
self.show("Process " + self.command + " terminated.\n\n")

except FileNotFoundError:
self.show("Unknown command: " + self.command + "\n\n")
except IndexError:
self.show("No command entered\n\n")

self.stop()


if __name__ == "__main__":
root = tk.Tk()
root.title("Console")
Console(root).pack(expand=True, fill="both")
root.mainloop()

关于python - 运行实时输出到 Tkinter GUI 的进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30410421/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com