繁体   English   中英

Python tkinter 维护 gui 并从 pipe 读取

[英]Python tkinter maintaining gui and reading from pipe

我正在尝试从子进程 pipe stdout 和 stderr 读取并同时更新 GUI。 但是我的代码正在等待所有 pipe 读取过程,然后全部更新。

import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
import subprocess
import threading
import time
from queue import *

class Application:
    
    # load main window of application
    def __init__(self, master):
        self.current_script_file_name = None
        self.q = Queue()

        self.window = master
        self.window.title("TK")
        self.window.rowconfigure(1, minsize = 600, weight = 2)
        self.window.columnconfigure(1, minsize = 600, weight= 2)

        # create frame for buttons and create buttons
        self.frame_buttons = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
        self.button_save = tk.Button(master = self.frame_buttons, text = "Save", command = self.save_script_to_file)
        self.button_run = tk.Button(master = self.frame_buttons, text = "Run", command = self.run_script_from_file)

        # create frame for tk.Text editor and output
        self.frame_text = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
        self.text_editor = tk.Text(self.frame_text)
        self.text_output = tk.Text(self.frame_text, background = "Black", foreground = "White")

        #adjust buttons
        self.button_save.grid(row = 0, column = 0, sticky = "ew", padx = 5, pady = 5)
        self.button_run.grid(row = 1, column = 0, sticky = "ew", padx = 5)
        self.frame_buttons.grid(row = 0, column = 0, sticky = "ns")

        #adjust text editor and text output
        self.text_editor.grid(row = 0, column = 0, sticky = "ew", padx = 10, pady = 10)
        self.text_output.grid(row = 1, column = 0, sticky = "ew", padx = 5, pady = 5)
        self.frame_text.grid(row = 0, column = 1, sticky = "ns")

        self.text_output.insert(tk.END, 'Script Result:\n')
        
    def run(self):
        self.window.mainloop()

    def save_script_to_file(self):
        file_path = asksaveasfilename(
            filetypes=[("Python Scripts", "*.py"), ("Kotlin Scripts", "*.kts*")]
        )
        if not file_path:
            return
        with open(file_path, "w") as output_file:
            text = self.text_editor.get(1.0, tk.END)
            output_file.write("#!/usr/bin/env python3\n")
            output_file.write(text)
            
        self.window.title(f"Text Editor Application - {file_path}")


    def run_script_from_file(self):
        # start thread so main window not going to freeze
        threading.Thread(target=self.run_script).start()
        self.update()



    def run_script(self):
        sub_proc = subprocess.Popen(['python','script.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        threading.Thread(target=self.pipe_reader, args=[sub_proc.stdout]).start()
        threading.Thread(target=self.pipe_reader, args=[sub_proc.stderr]).start()

    def update(self):
        while not self.q.empty():
            for source, line in iter(self.q.get, None):
                self.text_output.insert(tk.END,line)
        self.window.after(1000,self.update)


    def pipe_reader(self, pipe):
        try:
            with pipe:
                for line in iter(pipe.readline, b''):
                    self.q.put((pipe, line))
        finally:
            self.q.put(None)

if __name__ == '__main__':
    root = tk.Tk()
    app = Application(root)
    app.run()

run_script_from_file 是一个按钮命令。 而self.q是一个队列,属于这个函数的同一个class。

为什么我的 text_output tk.Text 字段没有尽快更新

脚本.py:

#!/usr/bin/env python3

import time

counter = 1
while counter < 6:
    print ("The current counter value: %d" % counter)
    counter = counter + 1
    time.sleep(1)


print(asd)

编辑:我把我所有的代码编辑:添加了 script.py

好的,所以这实际上并不太远。 一个常见的问题是,由于缓冲,您必须在-u模式下运行 python。 唯一真正的另一件事是让 tkinter 更新循环一直运行。 尝试这个:

import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
import subprocess
import threading
import time
from queue import *

class Application:

    # load main window of application
    def __init__(self, master):
        self.current_script_file_name = None
        self.q = Queue()

        self.window = master
        self.window.title("TK")
        self.window.rowconfigure(1, minsize = 600, weight = 2)
        self.window.columnconfigure(1, minsize = 600, weight= 2)

        # create frame for buttons and create buttons
        self.frame_buttons = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
        self.button_save = tk.Button(master = self.frame_buttons, text = "Save", command = self.save_script_to_file)
        self.button_run = tk.Button(master = self.frame_buttons, text = "Run", command = self.run_script_from_file)

        # create frame for tk.Text editor and output
        self.frame_text = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
        self.text_editor = tk.Text(self.frame_text)
        self.text_output = tk.Text(self.frame_text, background = "Black", foreground = "White")

        #adjust buttons
        self.button_save.grid(row = 0, column = 0, sticky = "ew", padx = 5, pady = 5)
        self.button_run.grid(row = 1, column = 0, sticky = "ew", padx = 5)
        self.frame_buttons.grid(row = 0, column = 0, sticky = "ns")

        #adjust text editor and text output
        self.text_editor.grid(row = 0, column = 0, sticky = "ew", padx = 10, pady = 10)
        self.text_output.grid(row = 1, column = 0, sticky = "ew", padx = 5, pady = 5)
        self.frame_text.grid(row = 0, column = 1, sticky = "ns")

        self.text_output.insert(tk.END, 'Script Result:\n')

        self.update()

    def save_script_to_file(self):
        file_path = asksaveasfilename(
            filetypes=[("Python Scripts", "*.py"), ("Kotlin Scripts", "*.kts*")]
        )
        if not file_path:
            return
        with open(file_path, "w") as output_file:
            text = self.text_editor.get(1.0, tk.END)
            output_file.write("#!/usr/bin/env python3\n")
            output_file.write(text)

        self.window.title(f"Text Editor Application - {file_path}")

    def run_script_from_file(self):
        sub_proc = subprocess.Popen(['python3', '-u','script.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        threading.Thread(target=self.pipe_reader, args=[sub_proc.stdout]).start()
        threading.Thread(target=self.pipe_reader, args=[sub_proc.stderr]).start()

    def update(self):
        while not self.q.empty():
            source, line = self.q.get()
            if line is None:
                line = "DONE"
            self.text_output.insert(tk.END,line)
        self.window.after(100, self.update)

    def pipe_reader(self, pipe):
        for line in iter(pipe.readline, b''):
            self.q.put((pipe, line))
        self.q.put((pipe, None))

if __name__ == '__main__':
    root = tk.Tk()
    app = Application(root)
    root.mainloop()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM