在 Python 中逐行输出到 GUI

Printing line by line output to GUI in Python

我想在 python 中将我的标准输出打印到 GUI。我正在使用 Tkinter。 这就是我正在为我工​​作

def get_likes_button():
    output = subprocess.Popen(['python', "getLikes.py"], stdout=subprocess.PIPE)
    s1 = output.stdout.read()
    text.delete("1.0",END)
    text.insert(INSERT,s1)

但是,我一次得到了全部输出。 我想要的是 GUI 应该像在终端上打印一样迭代打印输出。

所以,我试过了,但是点击按钮时出现错误

def get_likes_button():
    text.delete("1.0",END)
    with subprocess.Popen(['python', "getLikes.py"], stdout=subprocess.PIPE) as output:
        s1 = output.stdout.read()
        text.insert(INSERT,s1)

错误是

Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1489, in __call__
return self.func(*args)
File "gui.py", line 88, in get_likes_button
with subprocess.Popen(['python', "getLikes.py"], stdout=subprocess.PIPE) as output:
AttributeError: __exit__

你能建议我做什么吗?

我认为 subprocess.Popen 不能用在 with 子句中。我认为 check_output 是你需要的:

output = subprocess.check_output(['python', 'getLikes.py'])

Popen 不支持上下文管理器(即 with)因此出现错误。但也请注意,您的代码的两个版本之间没有实际区别。

您可以改为逐行阅读:

def get_likes_button():
    child = subprocess.Popen(['python', 'getLikes.py'], stdout=subprocess.PIPE)
    text.delete("1.0",END)
    for line in iter(child.stdout.readline, ''):
        text.insert(INSERT, line)
    child.stdout.close()
    child.wait()

for line in iter(child.stdout.readline, ''): 用于解决如果循环 for line in child.stdout:.

将遇到的缓冲问题

更新

尝试修改代码如下:

def get_likes_button():
    child = subprocess.Popen(['python', '-u', 'getLikes.py'], stdout=subprocess.PIPE)
    text.delete("1.0",END)
    for line in iter(child.stdout.readline, ''):
        text.insert(INSERT, line)
        text.see(END)
        text.update_idletasks()
    child.stdout.close()
    child.wait()

变化是:

  1. 在child、
  2. 中使用-u python选项进行无缓冲输出
  3. 调用text.see(END)将文本window滚动到底部 每个插入,
  4. 调用text.update_idletasks()给Tkinter一个更新的机会 文本小部件。

这可能有助于避免使用线程,但不利的一面是,当您的回调正在执行时,GUI 的其余部分将无响应。如果您的 child 进程是短暂的,这可能是可以接受的,如果 child 运行时间较长,则可能不可接受 - 这取决于您的应用程序。