2015-12-24 188 views
7

我有多个gz文件,总大小约为120GB。我想将这些文件解压(gzip)到相同的目录并删除现有的gz文件。目前我们正在手动完成,并且需要更多时间来使用gzip -d <filename>解压缩。
有没有办法通过创建python脚本或任何其他技术来并行解压缩这些文件。目前这些文件在Linux机器上。如何使用多线程解压缩python中的多个gz文件?

回答

0

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

通过在后台运行多个gunzip进程,可以加快整个文件集的解压缩速度。每个服务一组特定的文件。

你可以在BASH中简单地打个比方。将文件列表拆分为单独的命令,并使用&将其作为后台作业启动。然后wait为每个工作完成。

我会建议你有2到2 * N个就业机会。其中N是计算机上的核心数或逻辑处理器数。适当地进行试验以获得正确的数字。

您可以在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 

在上面的例子中,我选择了每个作业4个文件并开始两个单独的作业。您可以轻松扩展脚本以获得更多作业,每个进程有更多文件,并将文件名称作为命令行参数。

+0

感谢您的回复,但我想自动执行此过程。假设我的目录中有50个文件,那么我希望将这些文件解压缩为并行,以便我可以减少时间。目前,我有文件名与标准序列号01至50所以我传递前10个文件在一个gzip命令像明智我有5个进程。所以我想创建一个线程的前5个工作,如明智我可以启动10个线程。我的问题是可能在Python? – user3743797

+0

有了一点bash脚本,你可以得到这个。将bash脚本的命令行参数转换为数组。然后分成4个独立的数组。每个数组成为一个单独的'gzip -d'调用。我会看看我以后能不能继续工作...... – selbie

+0

@ user3743797 - 现在可以工作了。你可以调用'script.sh * .gz'或者它将完成你想要的。我建议将脚本放在与您要操作的文件集不同的目录中。 – selbie

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,以避免拖延过程,如果一些文件大于平均水平。

+0

嗨安德烈,谢谢你的回复。所以如果我理解得当。我们一次处理4个文件的权利?如果一个文件完成,它会选择下一个文件(第5个文件)。请确认。 – user3743797

+0

@ user3743797:这是正确的 –

+0

感谢您的确认,如果我不想硬编码的文件,而不是传递目录位置,以便它会拿起files.Does池。imap_unordered方法接受目录位置作为文件名的输入? – user3743797

相关问题