在 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()
变化是:
- 在child、
中使用-u
python选项进行无缓冲输出
- 调用
text.see(END)
将文本window滚动到底部
每个插入,
- 调用
text.update_idletasks()
给Tkinter一个更新的机会
文本小部件。
这可能有助于避免使用线程,但不利的一面是,当您的回调正在执行时,GUI 的其余部分将无响应。如果您的 child 进程是短暂的,这可能是可以接受的,如果 child 运行时间较长,则可能不可接受 - 这取决于您的应用程序。
我想在 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()
变化是:
- 在child、 中使用
- 调用
text.see(END)
将文本window滚动到底部 每个插入, - 调用
text.update_idletasks()
给Tkinter一个更新的机会 文本小部件。
-u
python选项进行无缓冲输出
这可能有助于避免使用线程,但不利的一面是,当您的回调正在执行时,GUI 的其余部分将无响应。如果您的 child 进程是短暂的,这可能是可以接受的,如果 child 运行时间较长,则可能不可接受 - 这取决于您的应用程序。