Python os.walk,保存状态的方法?

时间:2013-04-03 23:59:58

标签: python python-2.7

我需要遍历文件服务器上的所有文件,我希望能够在文件树中的任何位置停止该过程并在以后恢复它。可以用os.walk完成,还是需要从头开始实现?

编辑:理想情况下,我希望解决方案能够持久化,因此脚本可以停止并稍后重新启动。

1 个答案:

答案 0 :(得分:2)

os.walk是一个非常正常的生成器函数,这意味着您可以调用它,保存生成的生成器,并在您闲暇时迭代它。例如:

w = os.walk(root)

for root, dirs, files in w:
   if root == 'foo':
       break
   else:
       # usual stuff

print('Hey, we found foo')

for root, dirs, files in w:
    # usual stuff

你甚至可以w一个函数,或者从一个函数返回它,或者用它作为你最喜欢的itertools函数的迭代器等。


无法做的一件大事就是腌制它。因此,如果你想将它保存到磁盘(或数据库),那么你可以退出程序并从中断的地方继续,或者将它发送到子进程完成,或者其他什么,你不能这样做

如果你能够提前完成所有的步行而不是懒散地进行(也就是说,你不需要动态地修剪步行,而且时间和存储的时间与步行本身相比是相形见绌的。您的实际工作所需的存储空间,您可以坚持list(w)。然后,您只需要跟踪该列表以及您到目前为止所获得的索引(或仅保留wlist[index:]而不是wlistindex)。但对于某些用例,这是不可接受的。

幸运的是,walk在纯Python中实现,而且非常简单,因此您可以从the source复制代码并对其进行修改以使状态可持久化。问题在于状态是部分隐含的,通过yield的魔力,所以你必须要么将内部输出转换为内部,要么将其转换为等效的纯迭代解决方案。这是一个开始:

class Walk(object):
    def __init__(self, top):
        self.queue = [top]
    def __iter__(self):
        return self
    def __next__(self):
        top = self.queue.pop(0)
        names = os.listdir(top)
        dirs, nondirs = [], []
        for name in names:
            if os.path.isdir(os.path.join(top, name)):
                dirs.append(name)
            else:
                nondirs.append(name)
        self.queue.extend(os.path.join(top, dir) for dir in dirs)
        return top, dirs, nondirs

这不处理任何可选参数。 followlinks=Falseonerror是微不足道的。处理topdown=True的动态修剪并不是很棘手(只需隐藏topdirs,并在下一次调用开始时将子项排入队列,而不是将其置于此项的结尾。做topdown=False会有点痛苦,但仍然不会坏(你可以为标准的递归到迭代转换创建一个显式的状态堆栈,或者保持额外的deque ,或者只是创建,存储和迭代新的Walk对象列表。如果您不需要它们,请不要费心添加它们。

我相信这会pickle没有变化。 (如果没有,它可能是一个微不足道的__getstate__或一个近乎无关紧要的__reduce__远离工作。)如果你正在使用不同的持久性机制,真的,你需要坚持的只是这是一个Walkqueue self.queue的{​​{1}}对象(这只是一个字符串列表),因此应该很容易。