在Tkinter主循环中使用os.walk

时间:2013-08-15 03:26:13

标签: python tkinter

正如标题所示,我正在尝试在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(...))我最终可以得到我需要的一切(作为元组)。但是,我仍然希望听到其他一些答案。

1 个答案:

答案 0 :(得分:0)

我终于解决了这个问题,我有一个“解决方案”:

首先,使用return function()语句或仅调用function()最终会使事件循环挨饿。因此,我必须通过w.afterw.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()

...代码行将输出相同的内容。