Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用boto3在两个AWS S3存储桶之间移动文件_Python_Amazon S3_Boto - Fatal编程技术网

Python 使用boto3在两个AWS S3存储桶之间移动文件

Python 使用boto3在两个AWS S3存储桶之间移动文件,python,amazon-s3,boto,Python,Amazon S3,Boto,我必须使用pythonbotoapi在一个bucket到另一个bucket之间移动文件。(我需要它从第一个桶中“剪切”文件,然后在第二个桶中“粘贴”文件)。 最好的方法是什么 **注意:如果我有两个不同的访问密钥和密钥,这有关系吗?我认为boto S3文档回答了您的问题 通过boto将文件从一个bucket移动到另一个bucket实际上是密钥从源到目标的副本,然后从源删除密钥 您可以访问存储桶: import boto c = boto.connect_s3() src = c.get_bu

我必须使用pythonbotoapi在一个bucket到另一个bucket之间移动文件。(我需要它从第一个桶中“剪切”文件,然后在第二个桶中“粘贴”文件)。 最好的方法是什么


**注意:如果我有两个不同的访问密钥和密钥,这有关系吗?

我认为boto S3文档回答了您的问题

通过boto将文件从一个bucket移动到另一个bucket实际上是密钥从源到目标的副本,然后从源删除密钥

您可以访问存储桶:

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()

另请参见:

Bucket name必须是字符串而不是Bucket对象。 下面的变化对我有用

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

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())
如果您使用的是boto3(较新的boto版本),这非常简单

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

如果你想

创建已存储在AmazonS3中的对象的副本

然后是去博托的路

我是如何做到的:

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()

如果您有两个具有不同访问凭据的不同存储桶。将凭据相应地存储在~/.aws文件夹下的凭据和配置文件中

您可以使用以下方法从一个具有不同凭据的bucket复制对象,然后将该对象保存在另一个具有不同凭据的bucket中:

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())
导入boto3
session\u src=bot3.session.session(profile\u name=)
source\u s3\u r=session\u src.resource('s3'))
session\u dest=bot3.session.session(profile\u name=)
dest\u s3\u r=会话目标资源('s3')
#创建对源图像的引用
old_obj=源对象(,+)
#为目标映像创建引用
新对象=目标对象(,旧对象键)
#将图像上载到目标S3对象
new_obj.put(Body=old_obj.get()['Body'].read())

这两个bucket不需要在ACL或bucket策略中相互具有可访问性。

这是我用来在s3 bucket的子目录中移动文件的代码

# =============================================================================
# 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 

我的问题是如何复制文件…?这可能是最好的方法。请记住,如果您对其进行了版本控制,则原始存储桶中会留下阴影。此外,您可能希望在try:expect上包装您的副本,以便在获得副本之前不会删除。您还可以复制并跟踪副本,然后通过dst存储桶执行key.lookup()并确保它在那里,如果是,则执行orig.delete().Gal:键是对象,对象包含内容。通过移动密钥,可以有效地移动“文件”。想象一下,当你在计算机上复制文件时,在文件系统中移动文件指针,这是相同的方法。语法似乎不正确,应该是
dst。copy_key(k.key.name,src.name,k.key.name)
因为你需要指定存储桶和密钥名称(而不是它们的对象)-让我难住了一会儿:)@marty:谢谢,我认为你是对的,并相应地更新了答案。我如何在这里给出配置而不在我的环境变量中设置它们?不知道一个简单的方法。在运行驱动程序之前,我会从python中设置env变量。awscli不是基于boto吗?boto和awscli都基于botocore。然而,boto本身并不公开类似于aws s3 mv的API。我仍然没有进行适当的实验来证明
mv
并不等同于
cp
+
rm
,但我真诚地希望如此:)我认为对我来说主要的性能提升是由于awscli中的多线程,虽然我认为freek给出的以下答案更好,但我可以想象,如果您为用户设置了.aws/config和.aws/credentials,您可以使用
driver.main('--profile=myprofile s3mv source\u bucket target\u bucket--recursive'.split())
您不需要从资源对象的元数据中提取客户端。我发现直接遍历client.copy_对象(或client.copy)与建议答案中的参数相同,而且似乎更一致(我在meta中得到了很多404)当源和目标是两个具有两个不同访问密钥的存储桶时,这是如何工作的?移动和复制不是一回事。old_obj.get()['Body'].read()在上载到目标存储桶之前创建本地副本。有没有一种有效的方法可以直接从src复制到dest bucket?