我有一个小脚本可以处理数千个小文件。该操作需要一段时间,因此程序将进度输出到控制台。它在下面的代码中进行了模拟:
files = 5000 #Number of files
for i in range(files):
sys.stdout.write("\r{0} of {1}".format(i, files))
我喜欢这种输出进度的方式;控制台中仅打印一行。但是现在我想从 GUI (tkinter) 运行这个脚本,并且我希望将输出打印到状态栏(标签)。我现在有点不知如何实现这个。有没有办法可以在不编辑脚本的情况下处理 GUI 中的输出?
最佳答案
虽然您可以拦截stdout
并用它做任何您想做的事情,但这是一个坏主意 - 而且,即使您这样做,您的程序也不会首先要有意识。
您无法在 GUI 应用程序中运行“需要一段时间”的操作。当操作运行时,GUI 的主循环没有运行,这意味着整个 GUI 被卡住。除了给您一个沙滩球之外,这还意味着您所做的任何更改在您返回之前都不会可见。
如果你在另一个线程中执行该操作怎么办?好吧,那么它不会阻止 GUI 运行……但是您无法从主线程以外的任何线程与 Tkinter 小部件通信,因此这没有帮助。
因此,您需要做的就是一次执行一步操作,每次将其余操作安排为稍后执行的回调。
例如:
class StatusWriter(object):
def write(self, msg):
statusbar.config(text=msg[1:])
def count():
sys.stdout = StatusWriter()
i = 0
def step():
nonlocal i
sys.stdout.write("\r{} of {}".format(i, 50))
i += 1
if i == 50:
sys.stdout = sys.__stdout__
else:
root.after(100, step)
root.after(100, step)
但实际上,一旦你重写了东西,删除标准输出替换黑客就更有意义了:
def count():
sys.stdout = StatusWriter()
i = 0
def step():
nonlocal i
statusbar.config(text="{} of {}".format(i, 50))
i += 1
if i == 50:
sys.stdout = sys.__stdout__
else:
root.after(100, step)
root.after(100, step)
关于python - 在 tkinter 中使用 sys.stdout.write ("\r..."),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19526422/