很快得到文件夹的总大小
我想快速find使用Python的任何文件夹的总大小。
import os from os.path import join, getsize, isfile, isdir, splitext def GetFolderSize(path): TotalSize = 0 for item in os.walk(path): for file in item[2]: try: TotalSize = TotalSize + getsize(join(item[0], file)) except: print("error with file: " + join(item[0], file)) return TotalSize print(float(GetFolderSize("C:\\")) /1024 /1024 /1024)
这是我写的简单的脚本来获取文件夹的总大小,大约需要60秒(+ -5秒)。 通过使用多处理,我把它在四核机器上减less到23秒。
使用Windows文件浏览器只需要约3秒钟(右键单击属性以查看自己)。 那么有没有更快的方式来find一个文件夹的总大小接近的速度,Windows可以做到这一点?
Windows 7中,python2.6(search,但大多数时候人们使用了一个非常类似的方法我自己)先谢谢了。
你处于劣势
Windows资源pipe理器几乎肯定使用FindFirstFile
/ FindNextFile
来遍历目录结构并通过一次传递收集大小信息(通过lpFindFileData
),从而使每个文件本质上是一个单一的系统调用。
不幸的是,在这种情况下Python不是你的朋友。 从而,
-
os.walk
首先调用os.listdir
(内部调用FindFirstFile
/FindNextFile
)- 从这一点开始的任何额外的系统调用只能使你比Windows资源pipe理器慢
-
os.walk
然后调用os.listdir
(内部调用GetFileAttributesEx
– 或者,在Win2k之前,GetFileAttributes
+FindFirstFile
组合)返回的每个文件的isdir
来重新确定是否recursion -
os.walk
和os.listdir
将执行额外的内存分配 ,string和数组操作等来填充它们的返回值 - 然后你调用
os.walk
返回的每个文件的getsize
(它再次调用GetFileAttributesEx
)
这比Windows资源pipe理器每个文件多3倍的系统调用,加上内存分配和操作开销。
你可以使用Anurag的解决scheme,或者直接调用FindFirstFile
/ FindNextFile
并recursion(这应该与cygwin
或其他win32端口 du -s some_directory
的性能相当)。
请参阅os.py
os.walk
的实现, listdir
实现listdir
和win32_stat
(同时由isdir
和getsize
调用)。
请注意, 在所有平台 (Windows和* nices) 上 ,Python的os.walk
并不是最理想的,直到并包括Python3.1。 在Windows和* nices中, os.walk
可以在不调用isdir
情况下实现遍历,因为FindFirst
/ FindNext
(Windows)和opendir
/ readdir
(* nix)已经通过lpFindFileData->dwFileAttributes
(Windows)返回文件types, dirent::d_type
(* nix)。
也许违反直觉,对于大多数现代configuration(例如Win7和NTFS,甚至一些SMB实现), GetFileAttributesEx
比单个文件的FindFirstFile
慢两倍 (甚至可能比用FindNextFile
迭代目录慢)。
更新: Python 3.5包含新的PEP 471 os.scandir()
函数,它通过返回文件属性和文件名解决了这个问题。 这个新的function是用来加快内置os.walk()
(在Windows和Linux上)。 您可以使用PyPI上的scandir模块来获取旧版Python版本的这种行为,包括2.x.
如果你想要与浏览器相同的速度,为什么不使用Windows脚本来访问相同的function使用pythoncom例如
import win32com.client as com folderPath = r"D:\Software\Downloads" fso = com.Dispatch("Scripting.FileSystemObject") folder = fso.GetFolder(folderPath) MB = 1024 * 1024.0 print("%.2f MB" % (folder.Size / MB))
它将和explorer一样工作,你可以在http://msdn.microsoft.com/en-us/library/bstcxhf7(VS.85).aspx上阅读更多关于Scripting运行时的信息。
我将Python代码的性能与包含190k文件的15k目录树进行了比较,并将其与du(1)
命令进行了比较,该命令大概和OS一样快。 Python代码花费了3.3秒,而花费了0.8秒的时间。 这是在Linux上。
我不确定有多less东西要挤出Python代码。 还要注意,du的第一次运行花费了45秒,这明显是在相关的i节点在块caching之前; 因此这个性能在很大程度上取决于系统pipe理其存储的程度。 如果其中之一或两者都不会让我感到惊讶:
- os.path.getsize在Windows上是次优的
- Windowscaching一次计算的目录内容大小