我有多个gz文件,总大小约为120GB。我想将这些文件解压缩(gzip)到同一目录并删除现有的gz文件。目前我们手动执行此操作,使用gzip -d <filename>
解压缩需要更多时间
有没有办法可以通过创建python脚本或任何其他技术并行解压缩这些文件。目前这些文件位于Linux机器上。
答案 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)
使用gunzip
或gzip -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个文件并启动了两个单独的作业。您可以轻松扩展脚本以获得更多作业,每个进程有更多文件,并将文件名作为命令行参数。