我需要遍历文件服务器上的所有文件,我希望能够在文件树中的任何位置停止该过程并在以后恢复它。可以用os.walk完成,还是需要从头开始实现?
编辑:理想情况下,我希望解决方案能够持久化,因此脚本可以停止并稍后重新启动。
答案 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:]
而不是wlist
和index
)。但对于某些用例,这是不可接受的。
幸运的是,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=False
和onerror
是微不足道的。处理topdown=True
的动态修剪并不是很棘手(只需隐藏top
和dirs
,并在下一次调用开始时将子项排入队列,而不是将其置于此项的结尾。做topdown=False
会有点痛苦,但仍然不会太坏(你可以为标准的递归到迭代转换创建一个显式的状态堆栈,或者保持额外的deque ,或者只是创建,存储和迭代新的Walk
对象列表。如果您不需要它们,请不要费心添加它们。
我相信这会pickle
没有变化。 (如果没有,它可能是一个微不足道的__getstate__
或一个近乎无关紧要的__reduce__
远离工作。)如果你正在使用不同的持久性机制,真的,你需要坚持的只是这是一个Walk
为queue
self.queue
的{{1}}对象(这只是一个字符串列表),因此应该很容易。