从S3桶中下载300万个对象的最快方法

32 投票
2 回答
15772 浏览
提问于 2025-04-16 10:10

我尝试过用Python加上boto库、multiprocessing、S3cmd和J3tset,但都遇到了困难。

有没有什么建议呢?比如你们用过的现成脚本,或者我不知道的其他方法?

补充:

eventlet加boto是一个值得尝试的解决方案,下面有提到。这里找到了一篇不错的关于eventlet的参考文章 http://web.archive.org/web/20110520140439/http://teddziuba.com/2010/02/eventlet-asynchronous-io-for-g.html

我在下面添加了我现在正在使用的Python脚本。

2 个回答

5

使用eventlet可以让你的输入输出操作同时进行。你可以先写一个简单的函数,用urllib来下载一个对象。然后,利用GreenPile这个工具,把这个函数应用到一系列的输入网址上。一般来说,使用50到100个绿色线程(greenlets)就足够了。

36

好的,我根据@Matt Billenstien的提示找到了一个解决方案。这个方案使用了eventlet库。这里的第一步是最重要的,就是对标准输入输出库进行“猴子补丁”。

你可以用nohup在后台运行这个脚本,这样就完成了。

from eventlet import *
patcher.monkey_patch(all=True)

import os, sys, time
from boto.s3.connection import S3Connection
from boto.s3.bucket import Bucket

import logging

logging.basicConfig(filename="s3_download.log", level=logging.INFO)


def download_file(key_name):
    # Its imp to download the key from a new connection
    conn = S3Connection("KEY", "SECRET")
    bucket = Bucket(connection=conn, name="BUCKET")
    key = bucket.get_key(key_name)

    try:
        res = key.get_contents_to_filename(key.name)
    except:
        logging.info(key.name+":"+"FAILED")

if __name__ == "__main__":
    conn = S3Connection("KEY", "SECRET")
    bucket = Bucket(connection=conn, name="BUCKET")

    logging.info("Fetching bucket list")
    bucket_list = bucket.list(prefix="PREFIX")

    logging.info("Creating a pool")
    pool = GreenPool(size=20)

    logging.info("Saving files in bucket...")
    for key in bucket.list():
        pool.spawn_n(download_file, key.key)
    pool.waitall()

撰写回答