如何获取Python中os.walk的进度?
我有一段代码,用来搜索游戏文件的可执行文件,并返回它们所在的目录。我想要一个进度指示器,显示一下 os.walk
处理到哪一步了。我该怎么做呢?
我试过用 startpt = root.count(os.sep)
来判断进度,但这只是告诉我 os.walk
在目录树中走了多深。
def locate(filelist, root=os.curdir): #Find a list of files, return directories.
for path, dirs, files in os.walk(os.path.abspath(root)):
for filename in returnMatches(filelist, [k.lower() for k in files]):
yield path + "\\"
10 个回答
只需要显示一个不确定的进度条(比如那种显示一个小球来回弹跳的,或者像理发店的那种条纹效果)。这样用户就知道程序在做一些有用的事情,但不会让他们误以为完成需要多长时间。
这要看情况!
如果文件和文件夹分布得差不多均匀,你可以假设每个顶级文件夹花费的时间差不多,这样就能大致显示进度。但是如果它们分布得不均匀,那就不容易找到这个信息。你要么事先大致知道每个文件夹里有多少文件,要么就得用os.walk遍历整个目录两次(不过这只有在你的实际处理时间远远超过os.walk的时间时才有意义)。
举个例子,假设你有4个顶级文件夹,每个文件夹里有4个文件。如果你假设每个顶级文件夹占25%的进度,每个文件又占该文件夹25%的进度,那你就可以显示一个不错的进度指示器。但如果最后一个子文件夹里的文件比前几个多得多,你的进度指示器可能在你发现之前就已经显示到75%了。如果os.walk本身就是瓶颈(而不是你的处理),而且目录结构又是随机的(你事先不知道每个子树大概需要多长时间),那就很难解决这个问题。
当然,这还得假设每个文件的处理成本差不多一样……
我搞明白这个问题了。
我使用了os.listdir这个函数来获取顶层目录的列表,然后对os.walk返回的路径使用了.split函数,这样就能得到当前所在的第一级目录。
这样我就得到了一个顶层目录的列表,然后可以找到os.walk当前目录的索引,并把这个索引和列表的长度进行比较,从而得出完成的百分比。;)
不过这样得到的进度条并不是特别平滑,因为每个目录里的工作量可能不一样,但对我来说,进度条的平滑度并不是重点。不过如果想要更平滑,可以通过更深入地检查目录结构来实现。
这是我用来获取进度的最终代码:
def locateGameDirs(filelist, root=os.curdir): #Find a list of files, return directories.
toplevel = [folder for folder in os.listdir(root) if os.path.isdir(os.path.join(root, folder))] #List of top-level directories
fileset = set(filelist)
for path, dirs, files in os.walk(os.path.abspath(root)):
curdir = path.split('\\')[1] #The directory os.walk is currently in.
try: #Thrown here because there's a nonexistant(?) first entry.
youarehere = toplevel.index(curdir)
progress = int(((youarehere)/len(toplevel))*100)
except:
pass
for filename in returnMatches(filelist, [k.lower() for k in files]):
yield filename, path + "\\", progress
现在为了调试,我在代码的后面做了这个:
for wow in locateGameDirs(["wow.exe", "firefox.exe", "vlc.exe"], "C:\\"):
print wow
有没有什么简单的方法来去掉那个try/except?因为路径的第一次迭代给我的结果是空的...