我需要遍历文件服务器上的所有文件,并且我希望能够停止该过程并在以后在文件树中的任何位置恢复它。这可以用 os.walk 来完成,还是需要从头开始实现?
编辑:理想情况下,我希望解决方案是持久的,以便脚本可以停止并在以后恢复。
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:]而不是wlistand index)。但对于某些用例,这是不可接受的。
幸运的是,walk它是用纯 Python 实现的,而且非常简单,因此您可以从源代码复制代码并修改它以使状态持久化。问题是状态是部分隐式的,通过 的魔法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=False并且onerror是微不足道的。处理动态修剪 fortopdown=True并不复杂(只是 stashtop和dirs,并在下一次调用开始而不是在本次调用结束时将子项排入队列)。这样做topdown=False会更痛苦,但仍然不会太糟糕(您可以为标准的递归到迭代转换创建一个明确的状态堆栈,或者保留一个额外的双端队列,或者只是创建、存储和迭代一个列表新Walk对象)。如果您不需要它们,请不要费心添加它们。
我相信这pickle不会改变。(如果不是,它要么是微不足道的__getstate__要么是几乎微不足道的__reduce__工作。)如果您使用不同的持久性机制,实际上,您需要坚持的是这是一个Walk对象,它queue是self.queue(这只是一个列表字符串),所以这应该很容易。
| 归档时间: | 
 | 
| 查看次数: | 748 次 | 
| 最近记录: |