Как разархивировать несколько файлов gz в python, используя многопоточность?

7

У меня есть несколько файлов gz с общим размером около 120 ГБ. Я хочу разархивировать (gzip) эти файлы в тот же каталог и удалить существующий gz файл. В настоящее время мы делаем это вручную, и у вас больше времени на распаковку с помощью gzip -d <filename>.
Есть ли способ, которым я могу разархивировать эти файлы параллельно, создав python script или любую другую технику. В настоящее время эти файлы находятся на машине Linux.

Теги:
multithreading
gzip

2 ответа

8

Вы можете сделать это очень легко с многопроцессорными пулами:

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

Этот код породит несколько процессов, и каждый процесс будет извлекать один файл за раз.

Здесь я выбрал chunksize=1, чтобы избежать остановок процессов, если некоторые файлы больше среднего.

  • 0
    Привет, Андреа, спасибо за твой ответ. Так что, если я правильно понял. Мы обрабатываем 4 файла одновременно, верно? если один файл закончен, он выберет следующий файл (5-й файл). Пожалуйста, подтвердите.
  • 0
    @user3743797: user3743797: все верно
Показать ещё 4 комментария
0

Большая часть времени настенных часов, затрачиваемых на распаковку файла с помощью gunzip или gzip -d, будет выполняться из операций ввода-вывода (чтение и запись на диск). Это может быть даже больше, чем время, затрачиваемое на декомпрессию данных. Вы можете воспользоваться этим, имея несколько заданий gzip, идущих в фоновом режиме. Поскольку некоторые операции блокируются при вводе-выводе, другое задание может выполняться без ожидания в очереди.

Вы можете ускорить распаковку всего набора файлов с помощью нескольких процессов gunzip, работающих в фоновом режиме. Каждый из них обслуживает определенный набор файлов.

Вы можете взломать что-то легкое в BASH. Разделите список файлов на отдельные команды и используйте &, чтобы запустить его как фоновое задание. Затем wait для каждого завершения каждого задания.

Я бы рекомендовал, чтобы у вас было от 2 до 2 * N заданий, идущих одновременно. Где N - количество ядер или логических процессоров на вашем компьютере. Поэкспериментируйте, чтобы получить правильный номер.

Вы можете легко взломать что-то в BASH.

#!/bin/bash

argarray=( "$@" )
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

В приведенном выше примере я выбрал 4 файла на одно задание и начал два отдельных задания. Вы можете легко расширить script, чтобы иметь больше заданий, больше файлов для каждого процесса и взять имена файлов в качестве параметров командной строки.

  • 0
    Спасибо за ваш ответ, но я хочу автоматизировать этот процесс. Предположим, у меня в каталоге 50 файлов, и я хочу, чтобы они были распакованы параллельно, чтобы я мог сократить время. В настоящее время у меня есть имена файлов со стандартными порядковыми номерами от 01 до 50 поэтому я передаю первые 10 файлов в одной команде gzip, как мудро, у меня есть 5 процессов. Итак, я хочу создать поток для первых 5 заданий, как мудрый, я могу запустить 10 потоков. Мой вопрос, возможно ли это в python?
  • 0
    С небольшим количеством сценариев bash вы можете получить это. Преобразуйте параметры командной строки вашего bash-скрипта в массив. Затем разделите на 4 отдельных массива. Каждый массив становится отдельным вызовом gzip -d . Я посмотрю, смогу ли я что-нибудь проработать позже ...
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню