我需要使用Python Boto API将文件从一个存储桶移动到另一个存储桶。(我需要将文件从第一个存储桶中“剪切”并“粘贴”到第二个存储桶中)。
最佳的方法是什么?
**注意:如果我有两个不同的ACCESS KEYS和SECRET KEYS,这是否重要?
如果您正在使用较新版本的 boto3,则这很简单。
import boto3
s3 = boto3.resource('s3')
copy_source = {
'Bucket': 'mybucket',
'Key': 'mykey'
}
s3.meta.client.copy(copy_source, 'otherbucket', 'otherkey')
(文档)
我认为 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()
dst.copy_key(k.key.name, src.name, k.key.name)
,因为您需要指定存储桶和对象的名称(而不是它们的对象)- 让我困惑了一段时间 :) - Marty如果您有两个不同的存储桶并且拥有不同的访问凭据,请相应地将凭据存储在“~/.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或存储桶策略中,这两个存储桶无需相互访问。
相比于逐个复制并删除每个密钥的boto库,awscli对我来说完成工作的速度要快30倍。这可能是由于awscli中的多线程功能。如果你仍然希望从Python脚本中运行它而不是通过调用shell命令,请尝试以下内容:
安装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())
aws s3 mv
的API。我仍然没有进行适当的实验来证明mv
不等同于cp
+ rm
,但是我真诚地希望如此 :) 我认为对我主要的性能提升是由于awscli中的多线程处理,我可能可以通过自己实现它来达到相似的速度。 - Artem Fedosovdriver.main('--profile=myprofile s3 mv source_bucket target_bucket --recursive'.split())
。 - rabinnh如果您想创建一个已存储在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()
使用boto3在不同或同一存储桶之间进行复制非常容易,方法如下:
import boto3
s3 = boto3.resource('s3')
copy_source = {
'Bucket': 'mybucket',
'Key': 'mykey'
}
bucket = s3.Bucket('otherbucket')
bucket.copy(copy_source, 'otherkey')
# This is a managed transfer that will perform a multipart copy in
# multiple threads if necessary.
桶名称必须是字符串,而不是桶对象。 以下更改对我有用
for k in src.list():
dst.copy_key(k.key, src.name, k.key)
我这样做是为了在两个S3位置之间移动文件。
它处理以下情况:
import boto3
s3 = boto3.resource('s3')
vBucketName = 'xyz-data-store'
#Source and Target Bucket Instantiation
vTargetBkt = s3.Bucket('xyz-data-store')
vSourceBkt = s3.Bucket('xyz-data-store')
#List of File name prefixes you want to move
vSourcePath = ['abc/1/test1_', 'abc/1/test2_'
,'abc/1/test3_','abc/1/test4_']
#List of Folder names you want the files to be moved to
vTargetPath = ['abc/1/test1_', 'abc/1/test2_'
,'abc/1/test3_','abc/1/test4_']
for (sP, tP) in zip(vSourcePath,vTargetPath) :
for se_files in vSourceBkt.objects.filter(Prefix = sP, Delimiter = '/'):
SourceFileName = (se_files.key).split('/')[-1]
copy_source = {
'Bucket': vSourceBkt.name,
'Key': se_files.key
}
#print('SourceFileName ' + SourceFileName)
#print('se_files ' + se_files.key)
TargetFileName = str("{}{}".format(tP,SourceFileName))
print('TargetFileName ' + TargetFileName)
s3.meta.client.copy(copy_source, vBucketName, TargetFileName)
#Delete files in the Source when the code is working
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::SOURCE_BUCKET_NAME",
"arn:aws:s3:::SOURCE_BUCKET_NAME/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::DESTINATION_BUCKET_NAME",
"arn:aws:s3:::DESTINATION_BUCKET_NAME/*"
]
}
]
}
boto3_session = boto3.Session(aws_access_key_id=<your access key>,
aws_secret_access_key=<your secret_access_key>)
s3_resource = boto3_session.resource('s3')
bucket = s3_resource.Bucket("<source bucket name>")
for obj in bucket.objects.all():
obj_path = str(obj.key)
copy_source = {
'Bucket': "<source bucket name>",
'Key': obj_path
}
s3_resource.meta.client.copy(copy_source, "<destination bucket name>", obj_path)
import boto3
# object_key = 'posts/0173c352-f9f8-4bf1-a818-c99b4c9b0c18.jpg'
def move_from_s3_to_s3(object_key):
session_src = boto3.session.Session(aws_access_key_id="",
region_name="ap-south-1",
aws_secret_access_key="")
source_s3_r = session_src.resource('s3')
session_dest = boto3.session.Session(aws_access_key_id="",
region_name="ap-south-1",
aws_secret_access_key="")
dest_s3_r = session_dest.resource('s3')
# create a reference to source image
old_obj = source_s3_r.Object('source_bucket_name', object_key)
# create a reference for destination image
new_obj = dest_s3_r.Object('dest_bucket_name', object_key)
# upload the image to destination S3 object
new_obj.put(Body=old_obj.get()['Body'].read())