如何使用多线程在python中解压缩多个gz文件?

时间:2015-12-24 10:51:56

标签: python linux multithreading gzip

我有多个gz文件,总大小约为120GB。我想将这些文件解压缩(gzip)到同一目录并删除现有的gz文件。目前我们手动执行此操作,使用gzip -d <filename>解压缩需要更多时间 有没有办法可以通过创建python脚本或任何其他技术并行解压缩这些文件。目前这些文件位于Linux机器上。

2 个答案:

答案 0 :(得分:8)

您可以使用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

此代码将生成一些进程,每个进程将一次提取一个文件。

这里我选择了chunksize=1,以避免在某些文件大于平均值时停止进程。

答案 1 :(得分:1)

使用gunzipgzip -d解压缩文件所花费的大部分挂钟时间将来自I / O操作(读取和写入磁盘)。它甚至可能超过实际解压缩数据所花费的时间。您可以通过在后台运行多个gzip作业来利用此功能。由于某些作业在I / O上被阻止,因此无需等待队列即可实际运行另一个作业。

您可以通过在后台运行多个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个文件并启动了两个单独的作业。您可以轻松扩展脚本以获得更多作业,每个进程有更多文件,并将文件名作为命令行参数。