¿Hay una manera rápida de huella dactilar un gran número de archivos en pitón?

Estoy codificando un programa que tiene una función que compara las huellas dactilares del archivo (para los archivos ) y realiza acciones basadas en los datos. El problema es que al escalar hasta miles de archivos se necesita un tiempo relativamente largo para procesar. La prueba más reciente que corrí tomó 75.7 segundos para 676 archivos, dos veces, así que unos 2 minutos y medio.

El objetivo principal es detectar cambios entre un registro del árbol de directorios (establecido en un archivo yaml) y los dos caminos, o árboles de directorio, por lo que no puedo conseguir alrededor tener que apresurar cada archivo. ¿Hay alguna manera de que pueda precipitar parcialmente, o un método más rápido, o algo más? Gracias.

Código de la función de identificación:

from hashlib import md5

BLOCK_SIZE = 65536

def fingerprinter(file_path):
    hash_method = md5()
    with open(file_path, 'rb') as input_file:
        buf = input_file.read(BLOCK_SIZE)
        while len(buf) > 0:
            hash_method.update(buf)
            buf = input_file.read(BLOCK_SIZE)

    return hash_method.hexdigest()

Una versión simplificada del código que llama la función de la huella dactilar:

def query(x_path):
    directory_tree = {}
    for root, dirs, files in os.walk(x_path, topdown=True):
        for name in files:
            if not "/." in root and not name.startswith("."):
                file_base = os.path.join(root, name) ## Root = path | Name = file
                print(file_base)
                hash = fingerprinter(file_base)
                media[file_base.split("/")[-1]] = {"hash": hash}

    return directory_tree

EDIT:

Pregunta hecha hace 3 años, 4 meses, 27 días - Por gitguru


2 Respuestas:

  • Para acelerar el proceso de huella dactilar de un gran número de archivos en Python, puedes implementar una técnica llamada "multiprocessing" para realizar el cálculo de forma paralela. Esto te permitirá procesar varios archivos al mismo tiempo, aprovechando los múltiples núcleos de tu CPU.

    Aquí te dejo un ejemplo de cómo podrías modificar tu código para incluir multiprocessing:

    python
    from hashlib import md5
    from multiprocessing import Pool
    import os
    
    BLOCK_SIZE = 65536
    
    def fingerprinter(file_path):
        hash_method = md5()
        with open(file_path, 'rb') as input_file:
            buf = input_file.read(BLOCK_SIZE)
            while len(buf) > 0:
                hash_method.update(buf)
                buf = input_file.read(BLOCK_SIZE)
    
        return hash_method.hexdigest()
    
    def process_file(file_path):
        try:
            hash = fingerprinter(file_path)
            return {file_path.split("/")[-1]: {"hash": hash}}
        except Exception as e:
            print(f"Error processing file {file_path}: {e}")
            return None
    
    def query(x_path):
        directory_tree = {}
        files_to_process = []
    
        for root, dirs, files in os.walk(x_path, topdown=True):
            for name in files:
                if not "/." in root and not name.startswith("."):
                    file_base = os.path.join(root, name)
                    files_to_process.append(file_base)
    
        with Pool() as pool:
            results = pool.map(process_file, files_to_process)
            for result in results:
                if result:
                    directory_tree.update(result)
    
        return directory_tree
    
    

    En este ejemplo, se han añadido dos funciones nuevas: process_file que envuelve el cálculo de huella dactilar para un solo archivo, y query ha sido modificada para utilizar multiprocessing. Los archivos a procesar se almacenan en la lista files_to_process, y luego se utiliza Pool para paralelizar la ejecución de process_file en todos los archivos.

    Ten en cuenta que el rendimiento real obtenido dependerá de tu CPU y del número de núcleos disponibles, así como de la naturaleza de los archivos y el tamaño de los mismos. Experimenta con el número de procesos en Pool y otras configuraciones para obtener el mejor rendimiento en tu caso específico.

    Respondida el Dec 20, 2020 a las 16:43 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Optimizaciones para acelerar el proceso de huella digital:

    Procesamiento en paralelo: Utiliza múltiples procesos o subprocesos para procesar archivos simultáneamente. Esto puede reducir significativamente el tiempo total de procesamiento. Huella digital parcial: Solo calcula la huella digital para una parte específica del archivo, como el encabezado o el final. Esto puede acelerar el proceso si los cambios solo ocurren en esas partes. Caché de huellas digitales: Almacena las huellas digitales calculadas previamente para evitar volver a calcularlas para los archivos que no han cambiado. Huella digital incremental: Si los archivos se actualizan con poca frecuencia, calcula la huella digital incrementalmente solo para las partes modificadas del archivo. Optimización del algoritmo de huella digital: Utiliza un algoritmo de huella digital más rápido, como SHA-256 en lugar de MD5. Optimización de la lectura de archivos: Utiliza la lectura en búfer para leer el archivo en bloques más grandes, reduciendo el número de operaciones de lectura del sistema.

    Implementación de la paralelización:

    Para implementar el procesamiento en paralelo, puedes utilizar la biblioteca multiprocessing de Python:

    python
    from multiprocessing import Pool
    
    def fingerprint_worker(file_path):
        return fingerprinter(file_path)
    
    def fingerprinter_parallel(file_paths):
        with Pool() as pool:
            fingerprints = pool.map(fingerprint_worker, file_paths)
        return fingerprints
    

    Esta función fingerprinter_parallel toma una lista de rutas de archivo y devuelve una lista de huellas digitales correspondientes.

    Ejemplo de uso:

    ``python <h1>Suponiendo que tienes una lista de rutas de archivo enfilepaths`fingerprints = fingerprinterparallel(file_paths)

    Ahora tienes las huellas digitales calculadas en paralelo

    ```

    Recuerda optimizar aún más el código siguiendo las otras recomendaciones para obtener el mejor rendimiento posible.

    Respondida el Dec 20, 2020 a las 16:50 - por Gemini

    Votos positivos: 0 | Votos negativos: 0