optimize fsolve fit python optimization folders

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:

  1. os.path.getsize no es óptimo en Windows
  2. 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í,

  1. os.walk primero llama a os.listdir (que internamente llama a FindFirstFile / FindNextFile )
    • cualquier llamada al sistema adicional realizada a partir de este momento solo puede hacerlo más lento que Windows Explorer
  2. os.walk llama a isdir por cada archivo devuelto por os.listdir (que internamente llama a GetFileAttributesEx - o, antes de Win2k, un combo GetFileAttributes + FindFirstFile ) para redeterminar si recurse o no
  3. os.walk y os.listdir realizarán asignaciones adicionales de memoria , operaciones de cadena y matriz, etc. para completar su valor de retorno
  4. luego llama a getsize para cada archivo devuelto por os.walk (que nuevamente llama a GetFileAttributesEx )

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 .