2015-12-24 91 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

相關問題