Tüm dosyaları bir S3 Bucket'tan indirmek için Boto3


85

S3 kovasından dosya almak için boto3 kullanıyorum. Benzer bir işleve ihtiyacım varaws s3 sync

Mevcut kodum

#!/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'])

Bu, pakette yalnızca dosyalar olduğu sürece sorunsuz çalışıyor. Paketin içinde bir klasör varsa, bu bir hata veriyor

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'

Bu, boto3 kullanarak eksiksiz bir s3 kovası indirmenin uygun bir yolu mu? Klasörler nasıl indirilir.


Yanıtlar:


40

1000'den fazla nesneye sahip paketlerle çalışırken NextContinuationToken, en fazla 1000 anahtarlık sıralı kümeler üzerinde kullanan bir çözüm uygulamak gerekir . Bu çözüm önce nesnelerin bir listesini derler ve ardından yinelemeli olarak belirtilen dizinleri oluşturur ve mevcut nesneleri indirir.

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)

daha geniş bir kullanım alanı içerdiği için bunu kabul edilen yanıt olarak değiştirmek. Teşekkürler Grant
Shan

kodum sonsuz bir döngüye while next_token is not None:
giriyor

@gpd boto3 istemcisi, son sayfaya ulaştığında NextContinuationToken olmadan bir sayfa döndürüp while ifadesinden çıkacağından bu olmamalıdır. Boto3 API'sini kullanarak aldığınız son yanıtı yapıştırırsanız (yanıt değişkeninde saklanan ne varsa), o zaman sizin özel durumunuzda neler olup bittiğinin daha net olacağını düşünüyorum. Yalnızca test etmek için 'sonuçlar' değişkenini yazdırmayı deneyin. Tahminim, paketinizin hiçbir içeriğiyle eşleşmeyen bir önek nesnesi vermişsinizdir. Kontrol ettin mi
Grant Langseth

1
Digital Ocean ile çalışması için küçük değişikliklere ihtiyacınız olacağını unutmayın. burada
David D.

2
Bu kodu kullanarak şu hatayı alıyorum: 'NoneType' nesnesi yinelenemez: TypeError
NJones

76

Aynı ihtiyaçlarım var ve dosyaları yinelemeli olarak indiren aşağıdaki işlevi yarattım.

Dizinler, yalnızca dosya içeriyorlarsa yerel olarak oluşturulur.

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)

İşleve şu şekilde denir:

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

6
Bir kaynak ve müşteri oluşturmanız gerektiğini sanmıyorum. Bir müşterinin her zaman kaynakta mevcut olduğuna inanıyorum. Sadece kullanabilirsin resource.meta.client.
TheHerk

2
O "download_dir (istemci, kaynak, subdir.get ( 'Önek'), yerel, olması gerektiğini düşünüyorum kepçe )"
rm999

6
Bir alıyordum, OSError: [Errno 21] Is a directorybu yüzden if not file.get('Key').endswith('/')çözmek için download_file çağrısını sardım. Teşekkür ederim @glefait ve @Shan
user336828

5
aws s3 syncBoto3 kütüphanesinde aws-cli komutunun bir eşdeğeri yok mu?
greperror

8
distBurada ne var?
Rob Rose

49

Amazon S3, klasörlere / dizinlere sahip değildir. Bu bir olan düz dosya yapısı .

Dizinlerin görünümünü korumak için, yol adları Anahtar (dosya adı) nesnesinin bir parçası olarak saklanır . Örneğin:

  • images/foo.jpg

Bu durumda, tüm Anahtar images/foo.jpgsadece değil foo.jpg.

Sorunun, botoçağrılan bir dosyayı döndürmek my_folder/.8Df54234ve yerel dosya sistemine kaydetmeye çalışmaktan kaynaklandığından şüpheleniyorum . Ancak, yerel dosya sisteminiz my_folder/bölümü bir dizin adı olarak yorumlar ve bu dizin yerel dosya sisteminizde mevcut değildir .

Ya olabilir kesmek sadece tasarruf için dosya adını .8Df54234kısmı veya olurdu gerekli dizinleri oluşturmak dosyaları yazmadan önce. Çok düzeyli iç içe dizinler olabileceğini unutmayın.

Daha kolay bir yol , tüm bu işi sizin için yapacak olan AWS Komut Satırı Arayüzünü (CLI) kullanmak olabilir , örneğin:

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

Ayrıca syncyalnızca yeni ve değiştirilmiş dosyaları kopyalayan bir seçenek de vardır .


1
@j Bunu anlıyorum. Ama klasörün otomatik olarak oluşturulmasına ihtiyacım vardı aws s3 sync. Boto3'te mümkün mü?
Shan

4
Python kodunuzun bir parçası olarak bir dizin oluşturmayı dahil etmeniz gerekir. Anahtar bir dizin içeriyorsa (örneğin foo/bar.txt), fooaramadan önce dizini ( ) oluşturmaktan sorumlu olacaksınız s3.download_file. Otomatik bir yetenek değildir boto.
John Rotenstein

Burada, S3 s3.list_objects(Bucket='my_bucket_name')['Contents']klasörünün içeriği dinamiktir, bu nedenle klasör anahtarlarını kontrol etmem ve filtrelemem ve bunları oluşturmam gerekiyor.
Shan

2
Bir süre Boto3 ile oynadıktan sonra, burada listelenen AWS CLI komutu kesinlikle bunu yapmanın en kolay yoludur.
AdjunctProfessorFalcon

1
@Ben Lütfen eski (2015) bir soruya yorum olarak soru sormak yerine yeni bir Soru başlatın.
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
Temiz ve basit, bunu neden kullanmıyorsunuz? Diğer tüm çözümlerden çok daha anlaşılır. Koleksiyonlar arka planda sizin için pek çok şey yapıyor gibi görünüyor.
Joost

3
Bunun düzgün çalışması için önce tüm alt klasörleri oluşturmalısınız sanırım.
rpanai

2
Bu kod, S3'te ne kadar iç içe geçmiş olursa olsun, her şeyi en üst düzey çıktı dizinine yerleştirir. Ve eğer birden fazla dosya farklı dizinlerde aynı ada sahipse, bir diğerinin üzerine basacaktır. Bence bir satıra daha ihtiyacın var: os.makedirs(path)ve sonra indirme hedefi olmalı object.key.
Scott Smith

13

Şu anda aşağıdakileri kullanarak görevi başarıyorum

#!/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)

İşi yapmasına rağmen, bu şekilde yapmanın iyi olduğundan emin değilim. Bunu daha iyi bir şekilde başarmak için diğer kullanıcılara yardımcı olmak ve daha fazla yanıt vermek için burada bırakıyorum


9

Geç olmak hiç olmamasından iyidir :) Sayfalayıcı ile verilen önceki cevap gerçekten çok iyi. Ancak yinelemeli ve sonunda Python'un yineleme sınırlarına ulaşabilirsin. İşte birkaç ekstra kontrolle alternatif bir yaklaşım.

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
Got KeyError: 'Contents'. giriş yolu '/arch/R/storeincomelogs/, tam yol /arch/R/storeincomelogs/201901/01/xxx.parquet.
Mithril

3

Bunun için AWS CLI'yi aynı süreçte çalıştıran bir çözümüm var.

awscliPython lib olarak kurun :

pip install awscli

Ardından bu işlevi tanımlayın:

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)

Yürütmek için:

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

Ben de aynı fikri kullandım, ancak synckomutu kullanmadan ve daha çok basitçe komutu çalıştırarak aws s3 cp s3://{bucket}/{folder} {local_folder} --recursive. Süreler dakikalardan (neredeyse 1 saat) kelimenin tam anlamıyla saniyelere
düştü

Bu kodu kullanıyorum ancak tüm hata ayıklama günlüklerinin gösterildiği bir sorunla karşılaşıyorum. Bunu genel olarak beyan ettim: logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.WARNING) logger = logging.getLogger()ve yalnızca günlüklerin kökten çıkarılmasını istiyorum. Herhangi bir fikir?
Nisan Polubiec

1

Tüm dosyaları tek seferde almak çok kötü bir fikir, toplu halde almayı tercih etmelisiniz.

S3'ten belirli bir klasörü (dizini) almak için kullandığım bir uygulama,

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

ve yine de tüm kovayı almak istiyorsanız, @John Rotenstein'ın aşağıda belirtildiği gibi CIL aracılığıyla kullanın ,

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

Bu kod içeriği /tmp/dizinde indirecektir . İsterseniz dizini değiştirebilirsiniz.


0

Python kullanarak bir bash betiği çağırmak istiyorsanız, burada bir dosyayı S3 klasöründeki bir klasörden yerel bir klasöre (bir Linux makinesinde) yüklemek için basit bir yöntem verilmiştir:

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

Benzer gereksinimi aldım ve yukarıdaki çözümlerden birkaçını ve diğer web sitelerinde okuyarak yardım aldım, aşağıdaki komut dosyasını buldum, Sadece birine yardımcı olup olmayacağını paylaşmak istedim.

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

İşletim sistemi hatası 20'den kaçınmak için @glefait yanıtının sonunda bir if koşulu ile yeniden yayınlanıyor. Aldığı ilk anahtar, hedef yolda yazılamayan klasör adının kendisidir.

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

Bir süredir bu sorunla karşılaşıyorum ve geçtiğim tüm farklı forumlarda, neyin işe yaradığına dair tam bir uçtan uca keskin nişancı görmedim. Ben de devam ettim ve tüm parçaları aldım (kendi başıma bazı şeyler ekledim) ve uçtan uca eksiksiz bir S3 Downloader oluşturdum!

Bu sadece dosyaları otomatik olarak indirmekle kalmaz, eğer S3 dosyaları alt dizinlerdeyse, onları yerel depolamada oluşturur. Uygulamamın örneğinde, izinleri ve sahipleri ayarlamam gerekiyor, böylece onu da ekledim (gerekmiyorsa yorum yapılabilir).

Bu test edildi ve bir Docker ortamında (K8) çalışıyor, ancak yerel olarak test etmek / çalıştırmak istemeniz durumunda betiğe çevresel değişkenleri ekledim.

Umarım bu, S3 İndirme otomasyonunu bulma arayışında birine yardımcı olur. Ayrıca, gerektiğinde bunun nasıl daha iyi optimize edilebileceğine dair her türlü tavsiyeyi, bilgiyi vb. Memnuniyetle karşılıyorum.

#!/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

AWS S3 Belgelerinden (Bir S3 klasöründe klasörleri nasıl kullanabilirim?):

Amazon S3'te, paketler ve nesneler birincil kaynaklardır ve nesneler paketlerde depolanır. Amazon S3, bir dosya sisteminde göreceğiniz gibi bir hiyerarşi yerine düz bir yapıya sahiptir . Ancak kurumsal basitlik adına Amazon S3 konsolu, nesneleri gruplama aracı olarak klasör konseptini destekler. Amazon S3 bunu, nesneler için paylaşılan bir ad öneki kullanarak yapar (yani nesnelerin ortak bir dizeyle başlayan adları vardır). Nesne adlarına ayrıca anahtar adları da denir.

Örneğin, konsolda photos adlı bir klasör oluşturabilir ve içinde fotoğrafım.jpg adlı bir nesneyi saklayabilirsiniz. Nesne daha sonra photos / öneki olan photos / myphoto.jpg anahtar adıyla saklanır.

Geçerli dizine "mybucket" dan tüm dosyaları indirmek için kovanın saygı Taklit dizin yapısını (onlar zaten yok lokal varsa kova klasör oluşturma):

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)

Kodunuzla ilgili bir açıklama eklemeniz daha iyi olur.
johan

1
@johan, geri bildirim için teşekkürler! İlgili açıklama ekledim
Daria
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.