Ответ 1
Вы находитесь в невыгодном положении.
Проводник Windows почти наверняка использует FindFirstFile
/FindNextFile
, чтобы обойти структуру каталогов и собирать информацию о размере (через lpFindFileData
) за один проход, что делает по существу один системный вызов для каждого файла.
В этом случае Python, к сожалению, не ваш друг. Таким образом,
-
os.walk
первые вызовыos.listdir
(который внутренне вызываетFindFirstFile
/FindNextFile
)- любые дополнительные системные вызовы, сделанные с этой точки дальше, могут сделать вас медленнее, чем проводник Windows
-
os.walk
затем вызываетisdir
для каждого файла, возвращаемогоos.listdir
(который внутренне вызываетGetFileAttributesEx
- или, прежде чем Win2k, aGetFileAttributes
+FindFirstFile
комбо), чтобы переопределить, следует ли повторять или нет -
os.walk
иos.listdir
будут выполнять выделение дополнительной памяти, операции с строками и массивами и т.д., чтобы заполнить их возвращаемое значение - вы , затем вызовите
getsize
для каждого файла, возвращаемогоos.walk
(который снова вызываетGetFileAttributesEx
)
Это 3 раза больше системных вызовов на файл, чем проводник Windows, плюс распределение памяти и накладные расходы.
Вы можете либо использовать решение Anurag, либо попытаться вызвать FindFirstFile
/FindNextFile
напрямую и рекурсивно (что должно быть сопоставимо с производительностью cygwin
или другой win32-порт du -s some_directory
.)
Обратитесь к os.py
для реализации os.walk
, posixmodule.c
для реализации listdir
и win32_stat
(вызывается как isdir
, так и getsize
.)
Обратите внимание, что Python os.walk
является субоптимальным на всех платформах (Windows и * nices), вплоть до Python3.1. Как для Windows, так и для * nices os.walk
можно добиться обхода за один проход без вызова isdir
, поскольку оба FindFirst
/FindNext
(Windows) и opendir
/readdir
(* nix) уже возвращают тип файла через lpFindFileData->dwFileAttributes
(Windows) и dirent::d_type
(* nix).
Возможно, интуитивно, в большинстве современных конфигураций (например, Win7 и NTFS и даже некоторых реализациях SMB) GetFileAttributesEx
дважды как медленный, чем FindFirstFile
одного файла (возможно, даже медленнее, чем итерация над каталогом с FindNextFile
.)
Обновление: Python 3.5 включает новый PEP 471 os.scandir()
, которая решает эту проблему, возвращая атрибуты файла вместе с именем файла. Эта новая функция используется для ускорения встроенного os.walk()
(как для Windows, так и для Linux). Вы можете использовать модуль scandir на PyPI, чтобы получить это поведение для более старых версий Python, включая 2.x.