正如标题所示,我正在尝试在Tkinter主循环中使用os.walk
。我正在使用Python 3.3.0。
基本上,我有一个界面,当你按下按钮时,然后输入一个 for 循环,它迭代列表的元素(对于这种情况,它们是存档名称,稍后解压缩)然后调用os.walk
循环来执行一些比较选项。如果我没有在主窗口上显示任何内容,这不会是一个问题。由于我希望这需要一段时间,我计划添加一对时间计数器来记录和估计执行完整操作所需的时间。
我知道如果我在mainloop()
内输入 for 或 while 循环,我最终会挨饿mainloop
,因此定时器在循环结束之前不会更新。
我也知道w.update_idletasks()
,但这似乎只是更新循环中的内容。
我知道在mainloop
内部循环的最佳方法是递归地调用函数(通过回调机制或return语句)。但是,由于os.walk
是一个生成器,我不知道如何将它转换为递归函数。
以下是有问题的(简化)代码片段:
for file in ziplist:
try:
# some code in here
for dirpath, dirnames, filenames in os.walk(zipdirpath):
for files in filenames:
filepath = os.path.join(dirpath,files)[len(zipdirpath)+1:]
size += os.stat(os.path.join(dirpath,files)).st_size
print(filepath)
left.append(filepath)
print(size)
# some code in here
except:
# some code in here
finally:
# some code in here
我可以转换(或者至少我认为我可以)第一个循环到这样的东西:
def callback(): # to be called by Tkinter
def func(index=0):
if index > len(ziplist):
return
# some code in here
index += 1
func(index)
但我对如何对os.walk
循环做同样的事情感到有些困惑。因此,我的问题。
next(os.walk(...))
我最终可以得到我需要的一切(作为元组)。但是,我仍然希望听到其他一些答案。
答案 0 :(得分:0)
我终于解决了这个问题,我有一个“解决方案”:
首先,使用return function()
语句或仅调用function()
最终会使事件循环挨饿。因此,我必须通过w.after
或w.after_idle
递归调用所有相关函数。
最后,调用自身的函数涉及递归,对于某些长进程可能最终会使程序崩溃,尽管看起来Tkinter eventloop完全不同地管理这些东西。
这两个......
for dirpath, dirnames, filenames in os.walk(path):
print(dirpath, dirnames, filenames)
......还有这些......
walk_object = os.walk(path)
def func():
global walk_object
try:
dirpath, dirnames, filenames = next(walk_object)
print(dirpath, dirnames, filenames)
func() # or w.after(0,func) or w.after_idle(func)
except StopIteration:
return
func()
...代码行将输出相同的内容。