【问题标题】:Downloading a large archive from AWS Glacier using Boto使用 Boto 从 AWS Glacier 下载大型档案
【发布时间】:2015-01-16 13:58:13
【问题描述】:

我正在尝试使用 Python 包 Boto 从 Glacier 下载一个大型存档(约 1 TB)。我使用的当前方法如下所示:

import os
import boto.glacier
import boto
import time

ACCESS_KEY_ID = 'XXXXX'
SECRET_ACCESS_KEY = 'XXXXX'
VAULT_NAME = 'XXXXX'
ARCHIVE_ID = 'XXXXX'
OUTPUT = 'XXXXX'

layer2 = boto.connect_glacier(aws_access_key_id = ACCESS_KEY_ID,
                              aws_secret_access_key = SECRET_ACCESS_KEY)

gv = layer2.get_vault(VAULT_NAME)

job = gv.retrieve_archive(ARCHIVE_ID)
job_id = job.id

while not job.completed:
    time.sleep(10)
    job = gv.get_job(job_id)

if job.completed:
    print "Downloading archive"
    job.download_to_file(OUTPUT)

问题在于作业 ID 会在 24 小时后过期,这不足以检索整个存档。我需要将下载分成至少 4 个部分。我怎样才能做到这一点并将输出写入单个文件?

【问题讨论】:

  • 您的下载时间超过 24 小时?我的意思是,您受带宽限制?在 EC2 上,将其提取/重新发送到 S3,以便您稍后下载,或将其拉到 EC2 框并从那里下载。

标签: python amazon-web-services boto amazon-glacier


【解决方案1】:

看起来你可以像这样在调用job.download_to_file时简单地指定chunk_size参数:

if job.completed:
    print "Downloading archive"
    job.download_to_file(OUTPUT, chunk_size=1024*1024)

但是,如果您无法在 24 小时内下载所有块,我认为您不能选择仅下载您使用 layer2 错过的块。

第一种方法

使用 layer1 你可以简单地使用方法get_job_output 并指定你要下载的字节范围。

看起来像这样:

file_size = check_file_size(OUTPUT)

if job.completed:
    print "Downloading archive"
    with open(OUTPUT, 'wb') as output_file:
        i = 0
        while True:
            response = gv.get_job_output(VAULT_NAME, job_id, (file_size + 1024 * 1024 * i, file_size + 1024 * 1024 * (i + 1)))
            output_file.write(response)
            if len(response) < 1024 * 1024:
                break
            i += 1

使用此脚本,您应该能够在脚本失败时重新运行该脚本,并继续从您离开的地方下载存档。

第二种方法

通过挖掘 boto 代码,我在 Job 类中发现了一个“私有”方法,您也可以使用它:_download_byte_range。使用这种方法你仍然可以使用 layer2。

file_size = check_file_size(OUTPUT)

if job.completed:
    print "Downloading archive"
    with open(OUTPUT, 'wb') as output_file:
        i = 0
        while True:
            response = job._download_byte_range(file_size + 1024 * 1024 * i, file_size + 1024 * 1024 * (i + 1)))
            output_file.write(response)
            if len(response) < 1024 * 1024:
                break
            i += 1

【讨论】:

  • 我最终使用了方法 2,经过一些调整后效果很好。我添加了一个条件,如果 file_size != 0 则将写入方法设置为“ab”。这样,如果重新运行,输出将被附加而不是被覆盖。此外,字节范围元组的第二个元素偏移 1(需要 -1)。最后,我在 _download_to_fileob 源代码中添加了重试异常和哈希验证。
【解决方案2】:

您必须在 boto.connect_glacier 函数中添加 region_name,如下所示:

    layer2 = boto.connect_glacier(aws_access_key_id = ACCESS_KEY_ID,
                                aws_secret_access_key = SECRET_ACCESS_KEY,
                                region_name = 'your region name')

【讨论】:

    猜你喜欢
    • 2016-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多