2015-12-24 11 views
7

Ho più file gz con una dimensione totale di circa 120 GB. Voglio decomprimere (gzip) quei file nella stessa directory e rimuovere il file gz esistente. Attualmente lo stiamo facendo manualmente e ci vuole più tempo per decomprimere usando gzip -d <filename>.
C'è un modo per decomprimere questi file in parallelo creando uno script python o qualsiasi altra tecnica. Attualmente questi file sono su una macchina Linux.Come decomprimere più file gz in python usando il multi threading?

risposta

0

Un grande segmento del tempo di orologio da parete impiegato per decomprimere un file con gunzip o gzip -d sarà dalle operazioni di I/O (lettura e scrittura su disco). Potrebbe anche essere più del tempo speso per la decompressione dei dati. Puoi trarre vantaggio da questo fatto avendo più lavori gzip in background. Poiché alcuni lavori sono bloccati su I/O, un altro lavoro può effettivamente essere eseguito senza dover attendere in coda.

È possibile velocizzare la decompressione dell'intero set di file con più processi gunzip in esecuzione in background. Ognuno che serve un insieme specifico di file.

È possibile creare qualcosa di semplice in BASH. Dividi l'elenco dei file in comandi separati e usa & per avviarlo come lavoro in background. Quindi wait per ogni lavoro da finire.

Si consiglia di eseguire tra 2 e 2 processi * N contemporaneamente. Dove N è il numero di core o processori logici sul tuo computer. Sperimenta se necessario per ottenere il numero giusto.

È possibile montare facilmente qualcosa in BASH.

#!/bin/bash 

argarray=("[email protected]") 
len=${#argarray[@]} 

#declare 4 empty array sets 
set1=() 
set2=() 
set3=() 
set4=() 

# enumerate over each argument passed to the script 
# and round robin add it to one of the above arrays 

i=0 
while [ $i -lt $len ] 
do 

    if [ $i -lt $len ]; then 
     set1+=("${argarray[$i]}") 
     ((i++)) 
    fi 

    if [ $i -lt $len ]; then 
     set2+=("${argarray[$i]}") 
     ((i++)) 
    fi 

    if [ $i -lt $len ]; then 
     set3+=("${argarray[$i]}") 
     ((i++)) 
    fi 

    if [ $i -lt $len ]; then 
     set4+=("${argarray[$i]}") 
     ((i++)) 
    fi 
done 

# for each array, start a background job 
gzip -d ${set1[@]} & 
gzip -d ${set2[@]} & 
gzip -d ${set3[@]} & 
gzip -d ${set4[@]} & 

# wait for all jobs to finish  
wait 

Nell'esempio precedente, ho selezionato 4 file per lavoro e ho iniziato due lavori separati. È possibile estendere facilmente lo script per avere più lavori, più file per processo e prendere i nomi dei file come parametri della riga di comando.

+0

Grazie per la tua risposta, ma voglio automatizzare questo processo.Suppongo di avere 50 file nella mia directory quindi voglio che questi siano decompressi parallelamente in modo da poter ridurre il tempo.Corrente ho nomi di file con numeri di sequenza standard da Da 01 a 50 quindi sto passando i primi 10 file in un comando gzip come saggio ho 5 processi. So voglio creare un thread per i primi 5 lavori come saggio posso iniziare con 10 thread. La mia domanda è possibile in python? – user3743797

+0

Con un po 'di scripting bash, puoi ottenere questo. Converti i parametri della riga di comando del tuo script bash in un array. Quindi diviso in 4 array separati. Ogni array diventa una chiamata 'gzip -d' separata. Vedrò se riesco a elaborare qualcosa più tardi ... – selbie

+0

@ user3743797 - ora funziona. Puoi invocare 'script.sh * .gz' o e farà esattamente quello che vuoi. Suggerirei di avere lo script in una directory separata dal set di file su cui si desidera operare. – selbie

8

Si può fare questo molto facilmente con multiprocessing Pools:

import gzip 
import multiprocessing 
import shutil 

filenames = [ 
    'a.gz', 
    'b.gz', 
    'c.gz', 
    ... 
] 

def uncompress(path): 
    with gzip.open(path, 'rb') as src, open(path.rstrip('.gz'), 'wb') as dest: 
     shutil.copyfileobj(src, dest) 

with multiprocessing.Pool() as pool: 
    for _ in pool.imap_unordered(uncompress, filenames, chunksize=1): 
     pass 

Questo codice si riproducono alcuni processi, e ogni processo si estrarre un file alla volta.

Qui ho scelto chunksize=1, per evitare processi di stallo se alcuni file sono più grandi della media.

+0

Ciao Andrea, grazie per la tua risposta. Se capisco correttamente. Stiamo elaborando 4 file alla volta, giusto? se il file è finito, sceglierà il file successivo (5 ° file). Confermare. – user3743797

+0

@ user3743797: giusto –

+0

Grazie per la conferma, cosa succede se non voglio hardcode i file invece di passare il percorso della directory in modo che raccoglierà i file.il metodo imap_unordered accetta la posizione della directory come input per i nomi dei file? – user3743797

Problemi correlati