2015-12-24 16 views
7

Tôi có nhiều tệp gz với tổng kích thước khoảng 120GB. Tôi muốn giải nén (gzip) các tệp đó vào cùng một thư mục và xóa tệp gz hiện có. Hiện tại, chúng tôi đang thực hiện thủ công và mất nhiều thời gian hơn để giải nén bằng cách sử dụng gzip -d <filename>.
Có cách nào tôi có thể giải nén các tệp đó song song bằng cách tạo tập lệnh python hoặc bất kỳ kỹ thuật nào khác không. Hiện tại các tệp này nằm trên máy Linux.Làm thế nào để giải nén nhiều tập tin gz trong python bằng cách sử dụng đa luồng?

Trả lời

0

Một phần lớn thời gian đồng hồ treo tường dành giải nén tệp với gunzip hoặc gzip -d sẽ là từ các hoạt động I/O (đọc và ghi vào đĩa). Nó thậm chí có thể nhiều hơn thời gian thực sự giải nén dữ liệu. Bạn có thể tận dụng điều này bằng cách có nhiều công việc gzip đang chạy trong nền. Vì một số công việc bị chặn trên I/O, một công việc khác có thể thực sự chạy mà không phải đợi trong hàng đợi.

Bạn có thể tăng tốc độ giải nén toàn bộ tệp bằng cách có nhiều quá trình gunzip chạy trong nền. Mỗi phân phát một tập hợp tệp cụ thể.

Bạn có thể nạp tiền dễ dàng bằng BASH. Chia danh sách tập tin thành các lệnh riêng biệt và sử dụng & để khởi động nó làm công việc nền. Sau đó, wait cho mỗi công việc để hoàn thành.

Tôi khuyên bạn nên có từ 2 đến 2 * N công việc cùng một lúc. Trong đó N là số lõi hoặc bộ xử lý logic trên máy tính của bạn. Thử nghiệm khi thích hợp để nhận đúng số.

Bạn có thể chuyển một số thứ dễ dàng bằng 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 

Trong ví dụ trên, tôi đã chọn 4 tệp cho mỗi công việc và bắt đầu hai công việc riêng biệt. Bạn có thể dễ dàng mở rộng tập lệnh để có nhiều công việc hơn, nhiều tệp hơn cho mỗi quy trình và lấy tên tệp dưới dạng tham số dòng lệnh.

+0

Cảm ơn bạn đã trả lời, nhưng tôi muốn tự động hóa quá trình này. 01 đến 50 vì vậy tôi đang vượt qua 10 tập tin đầu tiên trong một lệnh gzip như khôn ngoan tôi có 5 processes.So tôi muốn tạo một thread cho 5 công việc đầu tiên như khôn ngoan tôi có thể bắt đầu 10 threads.My câu hỏi là nó có thể trong python? – user3743797

+0

Với một chút bash scripting, bạn có thể nhận được điều này. Chuyển đổi các tham số dòng lệnh của tập lệnh bash của bạn thành một mảng. Sau đó chia thành 4 mảng riêng biệt. Mỗi mảng trở thành một cuộc gọi 'gzip -d' riêng biệt. Tôi sẽ xem nếu tôi có thể làm việc gì đó sau này ... – selbie

+0

@ user3743797 - bây giờ nó hoạt động. Bạn có thể gọi 'script.sh * .gz' hoặc nó sẽ thực hiện chính xác những gì bạn muốn. Tôi khuyên bạn nên có tập lệnh trong một thư mục riêng biệt từ tập hợp các tệp bạn muốn hoạt động. – selbie

8

Bạn có thể làm điều này rất dễ dàng với 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 

Mã này sẽ đẻ trứng một vài quy trình, và mỗi quá trình sẽ trích xuất một tập tin tại một thời điểm.

Ở đây tôi đã chọn chunksize=1, để tránh quá trình trì hoãn nếu một số tệp lớn hơn mức trung bình.

+0

Xin chào Andrea, cảm ơn câu trả lời của bạn. Nếu tôi hiểu chính xác.Chúng tôi đang xử lý 4 tệp cùng một lúc? nếu một tệp được hoàn thành thì nó sẽ chọn tệp tiếp theo (tệp thứ 5) .Xin vui lòng xác nhận. – user3743797

+0

@ user3743797: đúng là –

+0

Cảm ơn bạn đã xác nhận, điều gì sẽ xảy ra nếu tôi không muốn mã hóa các tệp thay vì đi qua vị trí thư mục để nó sẽ nhận tệp.Do hồ bơi.imap_unordered phương pháp chấp nhận vị trí thư mục như đầu vào cho tên tập tin? – user3743797

Các vấn đề liên quan