python - fsolve - muy rápido obteniendo el tamaño total de la carpeta
scipy optimize minimize in python (3)
Comparé el rendimiento del código de Python con un árbol de directorios de 15k que contiene 190k archivos y lo comparé con el comando du(1)
que presumiblemente funciona tan rápido como el sistema operativo. El código de Python tomó 3.3 segundos comparado con du que tomó 0.8 segundos. Esto fue en Linux.
No estoy seguro de que haya mucho que exprimir del código de Python. Tenga en cuenta también que la primera ejecución de du tomó 45 segundos, lo que obviamente fue antes de que los i-nodes relevantes estuvieran en la memoria caché del bloque; por lo tanto, este rendimiento depende en gran medida de cuán bien el sistema está administrando su tienda. No me sorprendería si una o ambas cosas:
- os.path.getsize no es óptimo en Windows
- Windows almacena en caché el tamaño del contenido del directorio una vez calculado
Quiero encontrar rápidamente el tamaño total de cualquier carpeta usando 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)
Esa es la simple secuencia de comandos que escribí para obtener el tamaño total de la carpeta, tomó alrededor de 60 segundos (+ -5 segundos). Al usar multiprocesamiento, lo reduje a 23 segundos en una máquina de cuatro núcleos.
Usando el explorador de archivos de Windows solo toma ~ 3 segundos (haga clic con el botón derecho en> propiedades para verlo). Entonces, ¿hay una manera más rápida de encontrar el tamaño total de una carpeta cerca de la velocidad que windows puede hacerlo?
Windows 7, Python 2.6 (realizaba búsquedas pero la mayoría de las veces las personas usaban un método muy similar al mío) Gracias de antemano.
Estás en desventaja.
Windows Explorer casi con certeza utiliza FindFirstFile
/ FindNextFile
para recorrer la estructura del directorio y recopilar información de tamaño (a través de lpFindFileData
) en una sola pasada, haciendo lo que básicamente es una sola llamada al sistema por archivo.
Por desgracia, Python no es tu amigo en este caso. Así,
-
os.walk
primero llama aos.listdir
(que internamente llama aFindFirstFile
/FindNextFile
)- cualquier llamada al sistema adicional realizada a partir de este momento solo puede hacerlo más lento que Windows Explorer
-
os.walk
llama aisdir
por cada archivo devuelto poros.listdir
(que internamente llama aGetFileAttributesEx
- o, antes de Win2k, un comboGetFileAttributes
+FindFirstFile
) para redeterminar si recurse o no -
os.walk
yos.listdir
realizarán asignaciones adicionales de memoria , operaciones de cadena y matriz, etc. para completar su valor de retorno - luego llama a
getsize
para cada archivo devuelto poros.walk
(que nuevamente llama aGetFileAttributesEx
)
Eso es 3 veces más llamadas al sistema por archivo que Windows Explorer, además de asignación de memoria y gastos generales de manipulación.
Puede utilizar la solución de Anurag o intentar invocar FindFirstFile
/ FindNextFile
directa y recursiva (que debería ser comparable al rendimiento de un cygwin
u otro puerto win32 du -s some_directory
).
Consulte os.py
para la implementación de os.walk
, posixmodule.c
para la implementación de listdir
y win32_stat
(invocado por isdir
y getsize
).
Tenga en cuenta que os.walk
de Python os.walk
es óptimo en todas las plataformas (Windows y * nices), incluido Python3.1. Tanto en Windows como en * os.walk
podría atravesar en una sola pasada sin llamar a isdir
ya que FindFirst
/ FindNext
(Windows) y opendir
/ readdir
(* nix) ya devuelven el tipo de archivo a través de lpFindFileData->dwFileAttributes
(Windows) y dirent::d_type
(* nix).
Tal vez contra intuición, en la mayoría de las configuraciones modernas (por ejemplo, Win7 y NTFS, e incluso algunas implementaciones SMB) GetFileAttributesEx
es dos veces más lento que FindFirstFile
de un solo archivo (posiblemente incluso más lento que iterar sobre un directorio con FindNextFile
).
Actualización: Python 3.5 incluye la nueva función PEP 471 os.scandir()
que resuelve este problema devolviendo atributos de archivo junto con el nombre del archivo. Esta nueva función se usa para acelerar el os.walk()
tanto en Windows como en Linux). Puede usar el módulo scandir en PyPI para obtener este comportamiento para las versiones anteriores de Python, incluyendo 2.x.
Si desea la misma velocidad que el explorador, ¿por qué no utilizar las secuencias de comandos de Windows para acceder a la misma funcionalidad utilizando pythoncom, por ejemplo?
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))
Funcionará igual que el explorador, puede leer más sobre el tiempo de ejecución de scripting en http://msdn.microsoft.com/en-us/library/bstcxhf7(VS.85).aspx .