0

正如标题所示,我正在尝试os.walk在 Tkinter 主循环中使用。我正在使用 Python 3.3.0。

本质上,我有一个界面,当您按下按钮时,您然后输入一个for循环,该循环迭代列表的元素(在这种情况下,它们是存档名称,稍后会解压缩),然后调用os.walk循环执行一些比较选项。如果我没有在主窗口上显示任何内容,这将不是问题。由于我预计这需要一段时间,因此我计划添加一对时间计数器来记录和估计执行完整操作所需的时间。

我知道如果我在 a 中输入forwhile循环,mainloop()我最终会饿死mainloop,因此在循环结束之前不会更新计时器。我也知道,w.update_idletasks()但这似乎只会更新循环内的内容。

我知道在内部循环的最佳方法mainloop是让函数以递归方式调用自身(通过回调机制或返回语句)。但是,由于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(...)),我最终可以得到我需要的一切(作为一个元组)。但是,我仍然想听听其他一些答案。

4

1 回答 1

0

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

首先,使用return function()语句或仅调用function()最终会使事件循环挨饿。所以,我必须通过w.afteror递归调用所有相关函数w.after_idle

最后,调用自身的函数涉及递归,这对于一些长进程可能最终导致程序崩溃,尽管 Tkinter 事件循环似乎完全不同地管理这些事情。


这两个...

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()

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

于 2013-08-16T00:55:29.357 回答