Làm cách nào để tải xuống đồng thời nhiều tệp trong python?

Tập lệnh tải xuống nhiều tệp song song với sự hỗ trợ cho s3. //. http. //. https. // giao thức

Sự miêu tả

downloader.py

Cách sử dụng. python downloader.py url1 url2 url3

Cài đặt

hệ điều hành Mac. Một phiên bản Python đã được cài đặt
các cửa sổ. Bạn sẽ cần phải cài đặt một trong 2. phiên bản x có sẵn tại python. tổ chức

phụ thuộc

Một số gói Python bổ sung bắt buộc cần được cài đặt để chạy trên dòng lệnh. Dưới đây là danh sách các gói

AWS Boto3 là ​​SDK Python dành cho AWS. Boto3 có thể được sử dụng để tương tác trực tiếp với tài nguyên AWS từ tập lệnh Python

API S3 của Boto3 không có bất kỳ phương pháp nào để tải xuống song song nhiều tệp từ một nhóm S3. Bạn có tùy chọn tải xuống từng tệp một nhưng điều đó tốn thời gian

Trong hướng dẫn này, chúng tôi sẽ xem xét cách chúng tôi có thể tải xuống nhiều tệp song song để tăng tốc quá trình tải xuống nhiều tệp từ S3

Mục lục

Đa xử lý và đa luồng Python

Có hai cách để tải xuống nhiều tệp song song

  • đa xử lý
  • đa luồng

Do khóa trình thông dịch toàn cầu [GIL] trong Python, Đa xử lý là cách thực sự duy nhất để đạt được chủ nghĩa thực dụng thực sự. Đa xử lý tận dụng nhiều CPU và lõi. Đa xử lý là lý tưởng khi các tác vụ bị ràng buộc bởi CPU

Mặt khác, đa luồng rất hữu ích khi các tác vụ bị ràng buộc IO. Phân luồng thường có dung lượng bộ nhớ thấp hơn và khả năng truy cập bộ nhớ dùng chung làm cho nó trở thành một lựa chọn tuyệt vời cho các ứng dụng liên kết I/O

Để hiểu chi tiết hơn về sự khác biệt giữa hai loại này, hãy xem chủ đề này trên Stackoverflow

Boto3 w/Đa luồng

Theo tài liệu Boto3, clients an toàn cho luồng. Tuy nhiên, Tài nguyên và Phiên không an toàn cho luồng. Do đó, chúng tôi sẽ sử dụng client cấp thấp để đảm bảo mã của chúng tôi an toàn cho luồng

Bài viết này đi sâu hơn vào sự khác biệt giữa Khách hàng và Tài nguyên

Tải xuống nhiều tệp bằng Đa xử lý

Chúng tôi sẽ tận dụng ProcessPoolExecutor từ thư viện concurrent.futures để tạo Nhóm quy trình nhằm tải xuống song song nhiều tệp từ S3


import boto3.session
from concurrent import futures
from concurrent.futures import ProcessPoolExecutor
from pathlib import Path

KEYS_TO_DOWNLOAD = [...] # all the files that you want to download
BUCKET_NAME = "my-test-bucket"
LOCAL_DOWNLOAD_PATH = "files/"

def download_object[file_name]:
    """Downloads an object from S3 to local."""

    s3_client = boto3.client["s3"]
    download_path = Path[LOCAL_DOWNLOAD_PATH] / file_name
    print[f"Downloading {file_name} to {download_path}"]
    s3_client.download_file[
        BUCKET_NAME,
        file_name,
        str[download_path]
    ]
    return "Success"

def download_parallel_multiprocessing[]:
    with ProcessPoolExecutor[] as executor:
        future_to_key = {executor.submit[download_object, key]: key for key in KEYS_TO_DOWNLOAD}

        for future in futures.as_completed[future_to_key]:
            key = future_to_key[future]
            exception = future.exception[]

            if not exception:
                yield key, future.result[]
            else:
                yield key, exception

if __name__ == "__main__":
    for key, result in download_parallel_multiprocessing[]:
        print[f"{key}: {result}"]

Đầu ra của chương trình

Downloading sitemap.xml to files/sitemap.xml
Downloading feed.xml to files/feed.xml
Downloading robots.txt to files/robots.txt
Downloading index.html to files/index.html
index.html result: Success
robots.txt result: Success
sitemap.xml result: Success
feed.xml result: Success

Tải xuống nhiều tệp bằng Đa luồng

Chúng tôi sẽ sử dụng ThreadPoolExecutor từ thư viện concurrent.futures để tạo Nhóm luồng để tải xuống song song nhiều tệp từ S3. Không giống như ví dụ đa xử lý, chúng tôi sẽ chia sẻ máy khách S3 giữa các luồng vì đó là luồng an toàn


import boto3.session
from concurrent import futures
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path

KEYS_TO_DOWNLOAD = [...] # all the files that you want to download
BUCKET_NAME = "my-test-bucket"
LOCAL_DOWNLOAD_PATH = "files/"

def download_object[s3_client, file_name]:
    download_path = Path[DOWNLOAD_PATH] / file_name
    print[f"Downloading {file_name} to {download_path}"]
    s3_client.download_file[
        BUCKET_NAME,
        file_name,
        str[download_path]
    ]
    return "Success"

def download_parallel_multithreading[]:
    # Create a session and use it to make our client
    session = boto3.session.Session[]
    s3_client = session.client["s3"]

    # Dispatch work tasks with our s3_client
    with ThreadPoolExecutor[max_workers=8] as executor:
        future_to_key = {executor.submit[download_object, s3_client, key]: key for key in KEYS_TO_DOWNLOAD}

        for future in futures.as_completed[future_to_key]:
            key = future_to_key[future]
            exception = future.exception[]

            if not exception:
                yield key, future.result[]
            else:
                yield key, exception


if __name__ == "__main__":
    for key, result in download_parallel_multithreading[]:
        print[f"{key} result: {result}"]

Đầu ra của việc chạy chương trình này là

Downloading feed.xml to files/feed.xml
Downloading index.html to files/index.html
Downloading robots.txt to files/robots.txt
Downloading sitemap.xml to files/sitemap.xml
sitemap.xml result: Success
index.html result: Success
robots.txt result: Success
feed.xml result: Success

Hiệu suất

Hiệu suất giữa Đa xử lý và Đa luồng tương tự nhau trong các thử nghiệm mà tôi đã chạy. Có một cải tiến đáng kể so với việc tải xuống từng tệp một

Chủ Đề