web-dev-qa-db-ja.com

botoを使用して2つのAmazon S3バケット間でファイルを移動する方法は?

Python Boto APIを使用して、バケット間でファイルを移動する必要があります(最初のバケットからファイルを「カット」し、2番目のバケットに「貼り付け」する必要があります)。それを行う最善の方法は何ですか?

**注:2つの異なるアクセスキーとシークレットキーがある場合、問題になりますか?

25
Gal

Boto S3のドキュメントがあなたの質問に答えていると思います。

https://github.com/boto/boto/blob/develop/docs/source/s3_tut.rst

Botoを使用して1つのバケットから別のバケットにファイルを移動することは、ソースから宛先へのキーのコピーであり、ソースからキーを削除します。

バケットにアクセスできます:

import boto

c = boto.connect_s3()
src = c.get_bucket('my_source_bucket')
dst = c.get_bucket('my_destination_bucket')

キーを繰り返します:

for k in src.list():
    # copy stuff to your destination here
    dst.copy_key(k.key.name, src.name, k.key.name)
    # then delete the source key
    k.delete()

参照: s3cmdを使用して1つのS3バケットから別のバケットにすべてのファイルをコピーすることは可能ですか?

23

Boto3(新しいbotoバージョン)を使用している場合、これは非常に簡単です。

import boto3
s3 = boto3.resource('s3')
copy_source = {
    'Bucket': 'mybucket',
    'Key': 'mykey'
}
s3.meta.client.copy(copy_source, 'otherbucket', 'otherkey')

ドキュメント

17
David Arenburg

awscliは、botoの各キーの対処と削除よりも30倍速くジョブを実行します。おそらくawscliのマルチスレッド化が原因です。それでもシェルコマンドを呼び出さずにpythonスクリプトから実行したい場合は、次のようなものを試してみてください。

インストールawscli pythonパッケージ:

Sudo pip install awscli

そして、それはこれと同じくらい簡単です:

import os
if os.environ.get('LC_CTYPE', '') == 'UTF-8':
    os.environ['LC_CTYPE'] = 'en_US.UTF-8'

from awscli.clidriver import create_clidriver
driver = create_clidriver()
driver.main('s3 mv source_bucket target_bucket --recursive'.split())
7
Artem Fedosov

あなたがしたい場合は

すでにAmazon S3に保存されているオブジェクトのコピーを作成します。

それから copy_object はboto3に行く方法です。

方法:

import boto3

aws_access_key_id = ""
aws_secret_access_key = ""
bucket_from = ""
bucket_to = ""
s3 = boto3.resource(
    's3',
    aws_access_key_id=aws_access_key_id,
    aws_secret_access_key=aws_secret_access_key
)
src = s3.Bucket(bucket_from)

def move_files():
    for archive in src.objects.all():
        # filters on archive.key might be applied here

        s3.meta.client.copy_object(
            ACL='public-read',
            Bucket=bucket_to,
            CopySource={'Bucket': bucket_from, 'Key': archive.key},
            Key=archive.key
        )

move_files()
3
Tom Wojcik

バケット名は、バケットオブジェクトではなく文字列である必要があります。以下の変更が私のために働いた

for k in src.list():
    dst.copy_key(k.key, src.name, k.key)
3
SathishVenkat

異なるアクセス認証情報を持つ2つの異なるバケットがある場合。資格情報を〜/ .awsフォルダーの下の資格情報と構成ファイルに適宜保存します。

次を使用して、異なる資格情報を持つ1つのバケットからオブジェクトをコピーし、別の資格情報を持つ別のバケットにオブジェクトを保存できます。

import boto3


session_src = boto3.session.Session(profile_name=<source_profile_name>)
source_s3_r = session_src.resource('s3')

session_dest = boto3.session.Session(profile_name=<dest_profile_name>)
dest_s3_r = session_dest.resource('s3')

# create a reference to source image
old_obj = source_s3_r.Object(<source_s3_bucket_name>, <prefix_path> + <key_name>)

# create a reference for destination image
new_obj = dest_s3_r.Object(<dest_s3_bucket_name>, old_obj.key)

# upload the image to destination S3 object
new_obj.put(Body=old_obj.get()['Body'].read())

両方のバケットは、ACLまたはバケットポリシーで相互にアクセスできる必要はありません。

2
agrawalramakant

boto3.resource("s3").meta.client.copyの単一インスタンスconcurrent.futures.ThreadPoolExecutor はうまく機能します。同時実行コピーが機能するために、ローカルのAWS構成をカスタマイズする必要はないようです。

以下のようなパターンを使用しました。

import concurrent.futures

with concurrent.futures.ThreadPoolExecutor(max_workers=64, thread_name_prefix='S3Copier') as executor:
    for entry in your_iterable:  # Customize
        executor.submit(boto3.resource("s3").meta.client.copy,
                        {"Bucket": entry.src_bucket_name, "Key": entry.src_key},
                        entry.dest_bucket_name, entry.dest_key)
0
Acumenus

これは、s3バケットのサブディレクトリ内でファイルを移動するために使用したコードです

# =============================================================================
# CODE TO MOVE FILES within subfolders in S3 BUCKET
# =============================================================================

from boto3.session import Session

ACCESS_KEY = 'a_key'
SECRET_KEY = 's_key'
session = Session(aws_access_key_id=ACCESS_KEY,
            aws_secret_access_key=SECRET_KEY)
s3 = session.resource('s3')#creating session of S3 as resource


s3client = session.client('s3')

resp_dw = s3client.list_objects(Bucket='main_bucket', Prefix='sub_folder/', Delimiter="/")

forms2_dw = [x['Key'] for x in resp_dw['Contents'][1:]]#here we got all files list (max limit is 1000 at a time)
reload_no = 0
while len(forms2_dw) != 0 :

    #resp_dw = s3client.list_objects(Bucket='main_bucket', Prefix='sub_folder/', Delimiter="/")
    #with open('dw_bucket.json','w') as f:
    #    resp_dws =str(resp_dw)
       # f.write(json.dumps(resp_dws))
    #forms_dw = [x['Prefix'] for x in resp_dw['CommonPrefixes']] 
    #forms2_dw = [x['Key'] for x in resp_dw['Contents'][1:]]
    #forms2_dw[-1]
    total_files = len(forms2_dw)
    #i=0
    for i in range(total_files):
    #Zip_filename='1819.Zip'
        foldername = resp_dw['Contents'][1:][i]['LastModified'].strftime('%Y%m%d')#Put your logic here for folder name
        my_bcket   =  'main_bucket'

        my_file_old = resp_dw['Contents'][1:][i]['Key'] #file to be copied path
        Zip_filename =my_file_old.split('/')[-1]
        subpath_nw='new_sub_folder/'+foldername+"/"+Zip_filename #destination path
        my_file_new = subpath_nw
        # 
        print str(reload_no)+ ':::  copying from====:'+my_file_old+' to :====='+s3_archive_subpath_nw
        #print my_bcket+'/'+my_file_old 

        if Zip_filename[-4:] == '.Zip':
            s3.Object(my_bcket,my_file_new).copy_from(CopySource=my_bcket+'/'+my_file_old)
            s3.Object(my_bcket,my_file_old).delete()

            print str(i)+' files moved of '+str(total_files)

    resp_dw = s3client.list_objects(Bucket='main_bucket', Prefix='sub-folder/', Delimiter="/")

    forms2_dw = [x['Key'] for x in resp_dw['Contents'][1:]] 
    reload_no +=1 
0
Ganesh Kharad