Перемещение файлов между двумя корзинами AWS S3 с помощью boto3
Мне нужно переместить файлы между одним ведром в другое с помощью Python Boto API. (Мне нужно "Вырезать" файл из первого ковша и "Вставить" его во второй).
Каков наилучший способ сделать это?
** Примечание: Это имеет значение, если у меня есть два разных ключа доступа и СЕКРЕТНЫЕ КЛЮЧИ?
Ответы
Ответ 1
Я думаю, что документация boto S3 отвечает на ваш вопрос.
https://github.com/boto/boto/blob/develop/docs/source/s3_tut.rst
Перемещение файлов из одного сегмента в другое через boto - это фактически копия ключей от источника к месту назначения, а затем удаление ключа из источника.
Вы можете получить доступ к корзинам:
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()
См. также: Можно ли скопировать все файлы из одного сегмента S3 в другой с помощью s3cmd?
Ответ 2
Если вы используете boto3 (более новая версия boto), это довольно просто
import boto3
s3 = boto3.resource('s3')
copy_source = {
'Bucket': 'mybucket',
'Key': 'mykey'
}
s3.meta.client.copy(copy_source, 'otherbucket', 'otherkey')
(Документы)
Ответ 3
awscli выполняет работу в 30 раз быстрее, чем boto справляется и удаляет каждую клавишу. Вероятно, из-за многопоточности в awscli. Если вы все еще хотите запустить его из своего python script без вызова команд оболочки из него, вы можете попробовать что-то вроде этого:
Установить пакет 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())
Ответ 4
Имя байта должно быть строковым, а не ведомым.
Ниже изменения сработали для меня
for k in src.list():
dst.copy_key(k.key, src.name, k.key)
Ответ 5
Если хотите
Создайте копию объекта, который уже хранится в 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()
Ответ 6
Если у вас есть 2 разных сегмента с разными учетными данными. Сохраните учетные данные соответственно в учетных данных и конфигурационных файлах в папке ~/.aws.
Вы можете использовать следующее, чтобы скопировать объект из одного сегмента с другими учетными данными, а затем сохранить объект в другом сегменте с другими учетными данными:
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 или политиках сегмента.
Ответ 7
Это код, который я использовал для перемещения файлов в подкаталогах корзины 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