Boto3 để tải xuống tất cả các tệp từ Nhóm S3


82

Tôi đang sử dụng boto3 để lấy tệp từ thùng s3. Tôi cần một chức năng tương tự nhưaws s3 sync

Mã hiện tại của tôi là

#!/usr/bin/python
import boto3
s3=boto3.client('s3')
list=s3.list_objects(Bucket='my_bucket_name')['Contents']
for key in list:
    s3.download_file('my_bucket_name', key['Key'], key['Key'])

Điều này đang hoạt động tốt, miễn là nhóm chỉ có các tệp. Nếu một thư mục có bên trong thùng, nó sẽ gây ra lỗi

Traceback (most recent call last):
  File "./test", line 6, in <module>
    s3.download_file('my_bucket_name', key['Key'], key['Key'])
  File "/usr/local/lib/python2.7/dist-packages/boto3/s3/inject.py", line 58, in download_file
    extra_args=ExtraArgs, callback=Callback)
  File "/usr/local/lib/python2.7/dist-packages/boto3/s3/transfer.py", line 651, in download_file
    extra_args, callback)
  File "/usr/local/lib/python2.7/dist-packages/boto3/s3/transfer.py", line 666, in _download_file
    self._get_object(bucket, key, filename, extra_args, callback)
  File "/usr/local/lib/python2.7/dist-packages/boto3/s3/transfer.py", line 690, in _get_object
    extra_args, callback)
  File "/usr/local/lib/python2.7/dist-packages/boto3/s3/transfer.py", line 707, in _do_get_object
    with self._osutil.open(filename, 'wb') as f:
  File "/usr/local/lib/python2.7/dist-packages/boto3/s3/transfer.py", line 323, in open
    return open(filename, mode)
IOError: [Errno 2] No such file or directory: 'my_folder/.8Df54234'

Đây có phải là cách thích hợp để tải xuống thùng s3 hoàn chỉnh bằng boto3 không. Cách tải thư mục.


Câu trả lời:


34

Khi làm việc với các nhóm có hơn 1000 đối tượng, cần thiết để triển khai một giải pháp sử dụng các NextContinuationTokenbộ tuần tự tối đa là 1000 khóa. Giải pháp này đầu tiên biên dịch một danh sách các đối tượng sau đó tạo lặp đi lặp lại các thư mục được chỉ định và tải xuống các đối tượng hiện có.

import boto3
import os

s3_client = boto3.client('s3')

def download_dir(prefix, local, bucket, client=s3_client):
    """
    params:
    - prefix: pattern to match in s3
    - local: local path to folder in which to place files
    - bucket: s3 bucket with target contents
    - client: initialized s3 client object
    """
    keys = []
    dirs = []
    next_token = ''
    base_kwargs = {
        'Bucket':bucket,
        'Prefix':prefix,
    }
    while next_token is not None:
        kwargs = base_kwargs.copy()
        if next_token != '':
            kwargs.update({'ContinuationToken': next_token})
        results = client.list_objects_v2(**kwargs)
        contents = results.get('Contents')
        for i in contents:
            k = i.get('Key')
            if k[-1] != '/':
                keys.append(k)
            else:
                dirs.append(k)
        next_token = results.get('NextContinuationToken')
    for d in dirs:
        dest_pathname = os.path.join(local, d)
        if not os.path.exists(os.path.dirname(dest_pathname)):
            os.makedirs(os.path.dirname(dest_pathname))
    for k in keys:
        dest_pathname = os.path.join(local, k)
        if not os.path.exists(os.path.dirname(dest_pathname)):
            os.makedirs(os.path.dirname(dest_pathname))
        client.download_file(bucket, k, dest_pathname)

thay đổi câu trả lời này thành câu trả lời được chấp nhận vì nó xử lý trường hợp sử dụng rộng hơn. Cảm ơn Grant
Shan

mã của tôi đi vào một vòng lặp vô hạn lúcwhile next_token is not None:
gpd

@gpd điều này sẽ không xảy ra vì máy khách boto3 sẽ trả về một trang không có NextContinuationToken khi nó đã đến trang cuối cùng, thoát khỏi câu lệnh while. Nếu bạn dán phản hồi cuối cùng mà bạn nhận được từ việc sử dụng API boto3 (bất kỳ thứ gì được lưu trữ trong biến phản hồi) thì tôi nghĩ sẽ rõ ràng hơn những gì đang xảy ra trong trường hợp cụ thể của bạn. Hãy thử in biến 'kết quả' chỉ để kiểm tra. Tôi đoán là bạn đã đưa ra một đối tượng tiền tố không khớp với bất kỳ nội dung nào trong nhóm của bạn. Bạn đã kiểm tra điều đó?
Grant Langseth

Lưu ý rằng bạn sẽ cần những thay đổi nhỏ để làm cho nó hoạt động với Digital Ocean. như được giải thích ở đây
David D.

1
Sử dụng mã này, tôi gặp lỗi này: Đối tượng 'NoneType' không thể lặp lại: TypeError
NJones

76

Tôi có cùng nhu cầu và đã tạo hàm sau để tải xuống đệ quy các tệp.

Các thư mục chỉ được tạo cục bộ nếu chúng chứa tệp.

import boto3
import os

def download_dir(client, resource, dist, local='/tmp', bucket='your_bucket'):
    paginator = client.get_paginator('list_objects')
    for result in paginator.paginate(Bucket=bucket, Delimiter='/', Prefix=dist):
        if result.get('CommonPrefixes') is not None:
            for subdir in result.get('CommonPrefixes'):
                download_dir(client, resource, subdir.get('Prefix'), local, bucket)
        for file in result.get('Contents', []):
            dest_pathname = os.path.join(local, file.get('Key'))
            if not os.path.exists(os.path.dirname(dest_pathname)):
                os.makedirs(os.path.dirname(dest_pathname))
            resource.meta.client.download_file(bucket, file.get('Key'), dest_pathname)

Hàm được gọi theo cách đó:

def _start():
    client = boto3.client('s3')
    resource = boto3.resource('s3')
    download_dir(client, resource, 'clientconf/', '/tmp', bucket='my-bucket')

6
Tôi không nghĩ rằng bạn cần tạo một tài nguyên và một khách hàng. Tôi tin rằng khách hàng luôn có sẵn tài nguyên. Bạn chỉ có thể sử dụng resource.meta.client.
TheHerk

2
Tôi nghĩ rằng nên "download_dir (khách hàng, tài nguyên, subdir.get ( 'Tiền tố'), địa phương, )"
rm999

6
Tôi đã nhận được một OSError: [Errno 21] Is a directoryvì vậy tôi đã gọi đến download_file if not file.get('Key').endswith('/')để giải quyết. Cảm ơn bạn @glefait và @Shan
user336828

5
Không có lệnh aws s3 syncaws -cli tương đương có sẵn trong thư viện boto3?
greperror

8
Cái gì distở đây?
Rob Rose

49

Amazon S3 không có thư mục / thư mục. Nó là một cấu trúc tệp phẳng .

Để duy trì sự xuất hiện của các thư mục, tên đường dẫn được lưu trữ như một phần của Khóa đối tượng (tên tệp). Ví dụ:

  • images/foo.jpg

Trong trường hợp này, toàn bộ Key là images/foo.jpg, thay vì chỉ foo.jpg.

Tôi nghi ngờ rằng vấn đề của bạn là botođang trả về một tệp được gọi my_folder/.8Df54234và đang cố gắng lưu nó vào hệ thống tệp cục bộ. Tuy nhiên, hệ thống tệp cục bộ của bạn diễn giải my_folder/phần đó là tên thư mục và thư mục đó không tồn tại trên hệ thống tệp cục bộ của bạn .

Bạn có thể cắt bớt tên tệp để chỉ lưu một .8Df54234phần hoặc bạn sẽ phải tạo các thư mục cần thiết trước khi ghi tệp. Lưu ý rằng nó có thể là các thư mục lồng nhau nhiều cấp.

Một cách dễ dàng hơn sẽ là sử dụng Giao diện dòng lệnh AWS (CLI) , sẽ thực hiện tất cả công việc này cho bạn, ví dụ:

aws s3 cp --recursive s3://my_bucket_name local_folder

Cũng có một synctùy chọn sẽ chỉ sao chép các tệp mới và đã sửa đổi.


1
@j Tôi hiểu điều đó. Nhưng tôi cần thư mục được tạo tự động giống như vậy aws s3 sync. Có thể trong boto3.
Shan

4
Bạn sẽ phải bao gồm việc tạo một thư mục như một phần của mã Python của mình. Nếu Khóa chứa một thư mục (ví dụ foo/bar.txt), bạn sẽ chịu trách nhiệm tạo thư mục ( foo) trước khi gọi s3.download_file. Nó không phải là một khả năng tự động của boto.
John Rotenstein

Ở đây, nội dung của nhóm S3 là động, vì vậy tôi phải kiểm tra s3.list_objects(Bucket='my_bucket_name')['Contents']và lọc các khóa thư mục và tạo chúng.
Shan

2
Sau khi chơi với Boto3 một lúc, lệnh AWS CLI được liệt kê ở đây chắc chắn là cách dễ nhất để thực hiện việc này.
Trợ lý ProfessorFalcon

1
@Ben Vui lòng bắt đầu một Câu hỏi mới thay vì đặt một câu hỏi dưới dạng nhận xét về một câu hỏi cũ (2015).
John Rotenstein

43
import os
import boto3

#initiate s3 resource
s3 = boto3.resource('s3')

# select bucket
my_bucket = s3.Bucket('my_bucket_name')

# download file into current directory
for s3_object in my_bucket.objects.all():
    # Need to split s3_object.key into path and file name, else it will give error file not found.
    path, filename = os.path.split(s3_object.key)
    my_bucket.download_file(s3_object.key, filename)

3
Sạch sẽ và đơn giản, còn lý do gì mà không sử dụng cái này? Nó dễ hiểu hơn nhiều so với tất cả các giải pháp khác. Các bộ sưu tập dường như làm rất nhiều thứ cho bạn trong nền.
Joost

3
Tôi đoán trước tiên bạn nên tạo tất cả các thư mục con để điều này hoạt động bình thường.
rpanai

2
Mã này sẽ đặt mọi thứ vào thư mục đầu ra cấp cao nhất bất kể nó được lồng sâu như thế nào trong S3. Và nếu nhiều tệp có cùng tên trong các thư mục khác nhau, nó sẽ trùng tên với tệp khác. Tôi nghĩ bạn cần thêm một dòng:, os.makedirs(path)và sau đó đích tải xuống sẽ là object.key.
Scott Smith

13

Tôi hiện đang đạt được nhiệm vụ, bằng cách sử dụng

#!/usr/bin/python
import boto3
s3=boto3.client('s3')
list=s3.list_objects(Bucket='bucket')['Contents']
for s3_key in list:
    s3_object = s3_key['Key']
    if not s3_object.endswith("/"):
        s3.download_file('bucket', s3_object, s3_object)
    else:
        import os
        if not os.path.exists(s3_object):
            os.makedirs(s3_object)

Mặc dù, nó thực hiện công việc, tôi không chắc nó tốt khi làm theo cách này. Tôi để nó ở đây để giúp những người dùng khác và trả lời thêm, với cách tốt hơn để đạt được điều này


9

Muộn còn hơn không :) Câu trả lời trước với paginator thực sự rất tốt. Tuy nhiên, nó là đệ quy và bạn có thể sẽ đạt đến giới hạn đệ quy của Python. Đây là một cách tiếp cận thay thế, với một vài kiểm tra bổ sung.

import os
import errno
import boto3


def assert_dir_exists(path):
    """
    Checks if directory tree in path exists. If not it created them.
    :param path: the path to check if it exists
    """
    try:
        os.makedirs(path)
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise


def download_dir(client, bucket, path, target):
    """
    Downloads recursively the given S3 path to the target directory.
    :param client: S3 client to use.
    :param bucket: the name of the bucket to download from
    :param path: The S3 directory to download.
    :param target: the local directory to download the files to.
    """

    # Handle missing / at end of prefix
    if not path.endswith('/'):
        path += '/'

    paginator = client.get_paginator('list_objects_v2')
    for result in paginator.paginate(Bucket=bucket, Prefix=path):
        # Download each file individually
        for key in result['Contents']:
            # Calculate relative path
            rel_path = key['Key'][len(path):]
            # Skip paths ending in /
            if not key['Key'].endswith('/'):
                local_file_path = os.path.join(target, rel_path)
                # Make sure directories exist
                local_file_dir = os.path.dirname(local_file_path)
                assert_dir_exists(local_file_dir)
                client.download_file(bucket, key['Key'], local_file_path)


client = boto3.client('s3')

download_dir(client, 'bucket-name', 'path/to/data', 'downloads')

1
KeyError: 'Contents'. đường dẫn đầu vào '/arch/R/storeincomelogs/, đường dẫn đầy đủ /arch/R/storeincomelogs/201901/01/xxx.parquet.
Mithril

3

Tôi có một giải pháp cho việc này là chạy AWS CLI trong cùng một quy trình.

Cài đặt awsclidưới dạng python lib:

pip install awscli

Sau đó xác định chức năng này:

from awscli.clidriver import create_clidriver

def aws_cli(*cmd):
    old_env = dict(os.environ)
    try:

        # Environment
        env = os.environ.copy()
        env['LC_CTYPE'] = u'en_US.UTF'
        os.environ.update(env)

        # Run awscli in the same process
        exit_code = create_clidriver().main(*cmd)

        # Deal with problems
        if exit_code > 0:
            raise RuntimeError('AWS CLI exited with code {}'.format(exit_code))
    finally:
        os.environ.clear()
        os.environ.update(old_env)

Để thực hiện:

aws_cli('s3', 'sync', '/path/to/source', 's3://bucket/destination', '--delete')

Tôi đã sử dụng cùng một ý tưởng nhưng không sử dụng synclệnh, và chỉ đơn giản là thực hiện lệnh aws s3 cp s3://{bucket}/{folder} {local_folder} --recursive. Thời gian giảm từ phút (gần 1h) xuống theo nghĩa đen
acaruci

Tôi đang sử dụng mã này nhưng gặp sự cố khi tất cả nhật ký gỡ lỗi đang hiển thị. Tôi đã khai báo điều này trên toàn cầu: logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.WARNING) logger = logging.getLogger()và chỉ muốn các bản ghi được xuất ra từ thư mục gốc. Có ý kiến ​​gì không?
Tháng 4 Polubiec

1

Đó là một ý tưởng rất tồi khi lấy tất cả các tệp trong một lần, bạn nên lấy nó theo lô.

Một triển khai mà tôi sử dụng để tìm nạp một thư mục (thư mục) cụ thể từ S3 là,

def get_directory(directory_path, download_path, exclude_file_names):
    # prepare session
    session = Session(aws_access_key_id, aws_secret_access_key, region_name)

    # get instances for resource and bucket
    resource = session.resource('s3')
    bucket = resource.Bucket(bucket_name)

    for s3_key in self.client.list_objects(Bucket=self.bucket_name, Prefix=directory_path)['Contents']:
        s3_object = s3_key['Key']
        if s3_object not in exclude_file_names:
            bucket.download_file(file_path, download_path + str(s3_object.split('/')[-1])

và nếu bạn muốn toàn bộ nhóm, hãy sử dụng nó qua CIL như @John Rotenstein đã đề cập như bên dưới,

aws s3 cp --recursive s3://bucket_name download_path

0
for objs in my_bucket.objects.all():
    print(objs.key)
    path='/tmp/'+os.sep.join(objs.key.split(os.sep)[:-1])
    try:
        if not os.path.exists(path):
            os.makedirs(path)
        my_bucket.download_file(objs.key, '/tmp/'+objs.key)
    except FileExistsError as fe:                          
        print(objs.key+' exists')

Mã này sẽ tải xuống nội dung trong /tmp/thư mục. Nếu bạn muốn, bạn có thể thay đổi thư mục.


0

Nếu bạn muốn gọi một tập lệnh bash bằng python, đây là một phương pháp đơn giản để tải một tệp từ một thư mục trong nhóm S3 vào một thư mục cục bộ (trong máy Linux):

import boto3
import subprocess
import os

###TOEDIT###
my_bucket_name = "your_my_bucket_name"
bucket_folder_name = "your_bucket_folder_name"
local_folder_path = "your_local_folder_path"
###TOEDIT###

# 1.Load thes list of files existing in the bucket folder
FILES_NAMES = []
s3 = boto3.resource('s3')
my_bucket = s3.Bucket('{}'.format(my_bucket_name))
for object_summary in my_bucket.objects.filter(Prefix="{}/".format(bucket_folder_name)):
#     print(object_summary.key)
    FILES_NAMES.append(object_summary.key)

# 2.List only new files that do not exist in local folder (to not copy everything!)
new_filenames = list(set(FILES_NAMES )-set(os.listdir(local_folder_path)))

# 3.Time to load files in your destination folder 
for new_filename in new_filenames:
    upload_S3files_CMD = """aws s3 cp s3://{}/{}/{} {}""".format(my_bucket_name,bucket_folder_name,new_filename ,local_folder_path)

    subprocess_call = subprocess.call([upload_S3files_CMD], shell=True)
    if subprocess_call != 0:
        print("ALERT: loading files not working correctly, please re-check new loaded files")

0

Tôi nhận được yêu cầu tương tự và được trợ giúp từ việc đọc một vài giải pháp ở trên và trên các trang web khác, tôi đã đưa ra tập lệnh bên dưới, Tôi chỉ muốn chia sẻ nếu nó có thể giúp ích cho bất kỳ ai.

from boto3.session import Session
import os

def sync_s3_folder(access_key_id,secret_access_key,bucket_name,folder,destination_path):    
    session = Session(aws_access_key_id=access_key_id,aws_secret_access_key=secret_access_key)
    s3 = session.resource('s3')
    your_bucket = s3.Bucket(bucket_name)
    for s3_file in your_bucket.objects.all():
        if folder in s3_file.key:
            file=os.path.join(destination_path,s3_file.key.replace('/','\\'))
            if not os.path.exists(os.path.dirname(file)):
                os.makedirs(os.path.dirname(file))
            your_bucket.download_file(s3_file.key,file)
sync_s3_folder(access_key_id,secret_access_key,bucket_name,folder,destination_path)

0

Đăng lại câu trả lời của @glefait với điều kiện if ở cuối để tránh lỗi hệ điều hành 20. Chìa khóa đầu tiên nó nhận được là chính tên thư mục mà không thể viết trong đường dẫn đích.

def download_dir(client, resource, dist, local='/tmp', bucket='your_bucket'):
    paginator = client.get_paginator('list_objects')
    for result in paginator.paginate(Bucket=bucket, Delimiter='/', Prefix=dist):
        if result.get('CommonPrefixes') is not None:
            for subdir in result.get('CommonPrefixes'):
                download_dir(client, resource, subdir.get('Prefix'), local, bucket)
        for file in result.get('Contents', []):
            print("Content: ",result)
            dest_pathname = os.path.join(local, file.get('Key'))
            print("Dest path: ",dest_pathname)
            if not os.path.exists(os.path.dirname(dest_pathname)):
                print("here last if")
                os.makedirs(os.path.dirname(dest_pathname))
            print("else file key: ", file.get('Key'))
            if not file.get('Key') == dist:
                print("Key not equal? ",file.get('Key'))
                resource.meta.client.download_file(bucket, file.get('Key'), dest_pathname)enter code here

0

Tôi đã gặp phải vấn đề này trong một thời gian và với tất cả các diễn đàn khác nhau mà tôi đã xem qua, tôi không thấy một bản tóm tắt từ đầu đến cuối đầy đủ về những gì hoạt động. Vì vậy, tôi đã tiếp tục và lấy tất cả các phần (thêm một số thứ của riêng tôi) và đã tạo ra một Trình tải xuống S3 từ đầu đến cuối đầy đủ!

Thao tác này sẽ không chỉ tự động tải xuống tệp mà nếu tệp S3 nằm trong thư mục con, nó sẽ tạo chúng trên bộ nhớ cục bộ. Trong trường hợp ứng dụng của tôi, tôi cần đặt quyền và chủ sở hữu nên tôi cũng đã thêm quyền đó (có thể đưa ra bình luận nếu không cần thiết).

Điều này đã được thử nghiệm và hoạt động trong môi trường Docker (K8) nhưng tôi đã thêm các biến môi trường trong tập lệnh chỉ trong trường hợp bạn muốn thử nghiệm / chạy nó cục bộ.

Tôi hy vọng điều này sẽ giúp ai đó trong nhiệm vụ tìm kiếm tự động hóa Tải xuống S3. Tôi cũng hoan nghênh mọi lời khuyên, thông tin, v.v. về cách có thể tối ưu hóa điều này tốt hơn nếu cần.

#!/usr/bin/python3
import gc
import logging
import os
import signal
import sys
import time
from datetime import datetime

import boto
from boto.exception import S3ResponseError
from pythonjsonlogger import jsonlogger

formatter = jsonlogger.JsonFormatter('%(message)%(levelname)%(name)%(asctime)%(filename)%(lineno)%(funcName)')

json_handler_out = logging.StreamHandler()
json_handler_out.setFormatter(formatter)

#Manual Testing Variables If Needed
#os.environ["DOWNLOAD_LOCATION_PATH"] = "some_path"
#os.environ["BUCKET_NAME"] = "some_bucket"
#os.environ["AWS_ACCESS_KEY"] = "some_access_key"
#os.environ["AWS_SECRET_KEY"] = "some_secret"
#os.environ["LOG_LEVEL_SELECTOR"] = "DEBUG, INFO, or ERROR"

#Setting Log Level Test
logger = logging.getLogger('json')
logger.addHandler(json_handler_out)
logger_levels = {
    'ERROR' : logging.ERROR,
    'INFO' : logging.INFO,
    'DEBUG' : logging.DEBUG
}
logger_level_selector = os.environ["LOG_LEVEL_SELECTOR"]
logger.setLevel(logger_level_selector)

#Getting Date/Time
now = datetime.now()
logger.info("Current date and time : ")
logger.info(now.strftime("%Y-%m-%d %H:%M:%S"))

#Establishing S3 Variables and Download Location
download_location_path = os.environ["DOWNLOAD_LOCATION_PATH"]
bucket_name = os.environ["BUCKET_NAME"]
aws_access_key_id = os.environ["AWS_ACCESS_KEY"]
aws_access_secret_key = os.environ["AWS_SECRET_KEY"]
logger.debug("Bucket: %s" % bucket_name)
logger.debug("Key: %s" % aws_access_key_id)
logger.debug("Secret: %s" % aws_access_secret_key)
logger.debug("Download location path: %s" % download_location_path)

#Creating Download Directory
if not os.path.exists(download_location_path):
    logger.info("Making download directory")
    os.makedirs(download_location_path)

#Signal Hooks are fun
class GracefulKiller:
    kill_now = False
    def __init__(self):
        signal.signal(signal.SIGINT, self.exit_gracefully)
        signal.signal(signal.SIGTERM, self.exit_gracefully)
    def exit_gracefully(self, signum, frame):
        self.kill_now = True

#Downloading from S3 Bucket
def download_s3_bucket():
    conn = boto.connect_s3(aws_access_key_id, aws_access_secret_key)
    logger.debug("Connection established: ")
    bucket = conn.get_bucket(bucket_name)
    logger.debug("Bucket: %s" % str(bucket))
    bucket_list = bucket.list()
#    logger.info("Number of items to download: {0}".format(len(bucket_list)))

    for s3_item in bucket_list:
        key_string = str(s3_item.key)
        logger.debug("S3 Bucket Item to download: %s" % key_string)
        s3_path = download_location_path + "/" + key_string
        logger.debug("Downloading to: %s" % s3_path)
        local_dir = os.path.dirname(s3_path)

        if not os.path.exists(local_dir):
            logger.info("Local directory doesn't exist, creating it... %s" % local_dir)
            os.makedirs(local_dir)
            logger.info("Updating local directory permissions to %s" % local_dir)
#Comment or Uncomment Permissions based on Local Usage
            os.chmod(local_dir, 0o775)
            os.chown(local_dir, 60001, 60001)
        logger.debug("Local directory for download: %s" % local_dir)
        try:
            logger.info("Downloading File: %s" % key_string)
            s3_item.get_contents_to_filename(s3_path)
            logger.info("Successfully downloaded File: %s" % s3_path)
            #Updating Permissions
            logger.info("Updating Permissions for %s" % str(s3_path))
#Comment or Uncomment Permissions based on Local Usage
            os.chmod(s3_path, 0o664)
            os.chown(s3_path, 60001, 60001)
        except (OSError, S3ResponseError) as e:
            logger.error("Fatal error in s3_item.get_contents_to_filename", exc_info=True)
            # logger.error("Exception in file download from S3: {}".format(e))
            continue
        logger.info("Deleting %s from S3 Bucket" % str(s3_item.key))
        s3_item.delete()

def main():
    killer = GracefulKiller()
    while not killer.kill_now:
        logger.info("Checking for new files on S3 to download...")
        download_s3_bucket()
        logger.info("Done checking for new files, will check in 120s...")
        gc.collect()
        sys.stdout.flush()
        time.sleep(120)
if __name__ == '__main__':
    main()

0

Từ Tài liệu AWS S3 (Làm cách nào để sử dụng các thư mục trong nhóm S3?):

Trong Amazon S3, nhóm và đối tượng là tài nguyên chính và các đối tượng được lưu trữ trong nhóm. Amazon S3 có cấu trúc phẳng thay vì phân cấp như bạn thấy trong hệ thống tệp. Tuy nhiên, vì mục đích tổ chức đơn giản, bảng điều khiển Amazon S3 hỗ trợ khái niệm thư mục như một phương tiện nhóm các đối tượng. Amazon S3 thực hiện điều này bằng cách sử dụng tiền tố tên dùng chung cho các đối tượng (nghĩa là các đối tượng có tên bắt đầu bằng một chuỗi chung). Tên đối tượng cũng được gọi là tên khóa.

Ví dụ: bạn có thể tạo một thư mục trên bảng điều khiển có tên là ảnh và lưu trữ một đối tượng có tên myphoto.jpg trong đó. Đối tượng sau đó được lưu trữ với tên khóa là photos / myphoto.jpg, trong đó photos / là tiền tố.

Để tải xuống tất cả các tệp từ "mybucket" vào thư mục hiện tại theo cấu trúc thư mục được mô phỏng của nhóm (tạo các thư mục từ nhóm nếu chúng chưa tồn tại cục bộ):

import boto3
import os

bucket_name = "mybucket"
s3 = boto3.client("s3")
objects = s3.list_objects(Bucket = bucket_name)["Contents"]
for s3_object in objects:
    s3_key = s3_object["Key"]
    path, filename = os.path.split(s3_key)
    if len(path) != 0 and not os.path.exists(path):
        os.makedirs(path)
    if not s3_key.endswith("/"):
        download_to = path + '/' + filename if path else filename
        s3.download_file(bucket_name, s3_key, download_to)

Sẽ tốt hơn nếu bạn có thể bao gồm một số giải thích về mã của mình.
johan

1
@johan, cảm ơn vì phản hồi! Tôi đã thêm giải thích liên quan
Daria
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.