【发布时间】:2015-12-24 10:51:55
【问题描述】:
我有多个 gz 文件,总大小约为 120GB。我想将这些文件解压缩(gzip)到同一目录并删除现有的 gz 文件。目前我们正在手动进行,使用gzip -d <filename>解压缩需要更多时间。
有没有一种方法可以通过创建 python 脚本或任何其他技术来并行解压缩这些文件。目前这些文件位于 Linux 机器上。
【问题讨论】:
标签: python linux multithreading gzip
我有多个 gz 文件,总大小约为 120GB。我想将这些文件解压缩(gzip)到同一目录并删除现有的 gz 文件。目前我们正在手动进行,使用gzip -d <filename>解压缩需要更多时间。
有没有一种方法可以通过创建 python 脚本或任何其他技术来并行解压缩这些文件。目前这些文件位于 Linux 机器上。
【问题讨论】:
标签: python linux multithreading gzip
您可以使用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,以避免在某些文件大于平均值时导致进程停止。
【讨论】:
filenames 这里是硬编码的,但它可以是os.listdir() 或glob() 的结果。这取决于你。
Pool。最佳数量取决于核心数量,Pool 默认使用正确的数量。强制 4 只有一个“正面”效果,即您知道将使用多少个进程(这可能对调试有用)和一个强烈的负面效果,即在 4 核 CPU 上它与Pool() 和任何其他 cpu 会运行得更慢。
用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 个文件并开始了两个单独的作业。您可以轻松扩展脚本以拥有更多作业、每个进程更多文件,并将文件名作为命令行参数。
【讨论】:
gzip -d 调用。我会看看我以后能不能做点什么……
script.sh *.gz 或者它会做你想做的事。我建议将脚本放在与您要操作的文件集不同的目录中。