list_objects example create aws python amazon-web-services amazon-s3 boto3

python - example - Recuperando nombres de subcarpetas en el depósito S3 de boto3



python s3 bucket (7)

La pieza debajo del código devuelve SOLAMENTE las ''subcarpetas'' en una ''carpeta'' del cubo s3.

import boto3 bucket = ''my-bucket'' #Make sure you provide / in the end prefix = ''prefix-name-with-slash/'' client = boto3.client(''s3'') result = client.list_objects(Bucket=bucket, Prefix=prefix, Delimiter=''/'') for o in result.get(''CommonPrefixes''): print ''sub folder : '', o.get(''Prefix'')

Para más detalles, puede consultar https://github.com/boto/boto3/issues/134

Utilizando boto3, puedo acceder a mi cubo AWS S3:

s3 = boto3.resource(''s3'') bucket = s3.Bucket(''my-bucket-name'')

Ahora, el depósito contiene la carpeta de first-level , que a su vez contiene varias subcarpetas nombradas con una marca de tiempo, por ejemplo 1456753904534 . Necesito saber el nombre de estas subcarpetas para otro trabajo que estoy haciendo y me pregunto si podría hacer que boto3 las recupere.

Así que lo intenté:

objs = bucket.meta.client.list_objects(Bucket=''my-bucket-name'')

que da un diccionario, cuya clave "Contenido" me da todos los archivos de tercer nivel en lugar de los directorios de marca de tiempo de segundo nivel; de hecho, recibo una lista que contiene cosas como

{u''ETag '':'' "etag" '', u''Key'': primer nivel / 1456753904534 / part-00014 '', u''LastModified'': datetime.datetime (2016, 2, 29, 13, 52, 24, tzinfo = tzutc ()),
u''Owner '': {u''DisplayName'': ''propietario'', u''ID '':'' id ''},
u''Size '': size, u''StorageClass'': ''storageclass''}

Puede ver que se recuperan los archivos específicos, en este caso part-00014 , mientras que me gustaría obtener el nombre del directorio solo. En principio, podría quitar el nombre del directorio de todas las rutas, ¡pero es feo y costoso recuperar todo en el tercer nivel para obtener el segundo nivel!

También intenté algo reportado aquí :

for o in bucket.objects.filter(Delimiter=''/''): print(o.key)

pero no obtengo las carpetas en el nivel deseado.

¿Hay una manera de resolver esto?


S3 es un almacenamiento de objetos, no tiene una estructura de directorios real. El "/" es bastante cosmético. Una de las razones por las que las personas desean tener una estructura de directorio es porque pueden mantener / podar / agregar un árbol a la aplicación. Para S3, usted trata dicha estructura como un tipo de índice o etiqueta de búsqueda.

Para manipular objetos en S3, necesita boto3.client o boto3.resource, por ejemplo, para listar todos los objetos

import boto3 s3 = boto3.client("s3") all_objects = s3.list_objects(Bucket = ''my-bucket-name'')

http://boto3.readthedocs.org/en/latest/reference/services/s3.html#S3.Client.list_objects

Un recordatorio sobre boto3: boto3.resource es una buena API de alto nivel. Hay pros y contras usando boto3.client vs boto3.resource. Si desarrolla una biblioteca compartida interna, el uso de boto3.resource le dará una capa de blackbox sobre los recursos utilizados.


En primer lugar, no existe un concepto de carpeta real en S3. Definitivamente puede tener un archivo @ ''/folder/subfolder/myfile.txt'' y ninguna carpeta ni subcarpeta.

Para "simular" una carpeta en S3, debe crear un archivo vacío con un ''/'' al final de su nombre (consulte el boto de Amazon S3: ¿cómo crear una carpeta? )

Para su problema, probablemente debería usar el método get_all_keys con los 2 parámetros: prefix y delimiter

https://github.com/boto/boto/blob/develop/boto/s3/bucket.py#L427

for key in bucket.get_all_keys(prefix=''first-level/'', delimiter=''/''): print(key.name)



Me tomó mucho tiempo averiguarlo, pero finalmente aquí hay una manera simple de mostrar los contenidos de una subcarpeta en el cubo S3 usando boto3. Espero eso ayude

prefix = "folderone/foldertwo/" s3 = boto3.resource(''s3'') bucket = s3.Bucket(name="bucket_name_here") FilesNotFound = True for obj in bucket.objects.filter(Prefix=prefix): print(''{0}:{1}''.format(bucket.name, obj.key)) FilesNotFound = False if FilesNotFound: print("ALERT", "No file in {0}/{1}".format(bucket, prefix))


El AWS cli hace esto (presumiblemente sin buscar e iterar a través de todas las claves en el cubo) cuando ejecuta aws s3 ls s3://my-bucket/ , así que pensé que debe haber una forma de usar boto3.

https://github.com/aws/aws-cli/blob/0fedc4c1b6a7aee13e2ed10c3ada778c702c22c3/awscli/customizations/s3/subcommands.py#L499

Parece que de hecho usan Prefix y Delimiter: pude escribir una función que me proporcionaría todos los directorios en el nivel raíz de un segmento modificando un poco ese código:

def list_folders_in_bucket(bucket): paginator = boto3.client(''s3'').get_paginator(''list_objects'') folders = [] iterator = paginator.paginate(Bucket=bucket, Prefix='''', Delimiter=''/'', PaginationConfig={''PageSize'': None}) for response_data in iterator: prefixes = response_data.get(''CommonPrefixes'', []) for prefix in prefixes: prefix_name = prefix[''Prefix''] if prefix_name.endswith(''/''): folders.append(prefix_name.rstrip(''/'')) return folders


Lo siguiente funciona para mí ... Objetos S3:

s3://bucket/ form1/ section11/ file111 file112 section12/ file121 form2/ section21/ file211 file112 section22/ file221 file222 ... ... ...

Utilizando:

from boto3.session import Session s3client = session.client(''s3'') resp = s3client.list_objects(Bucket=bucket, Prefix='''', Delimiter="/") forms = [x[''Prefix''] for x in resp[''CommonPrefixes'']]

obtenemos:

form1/ form2/ ...

Con:

resp = s3client.list_objects(Bucket=bucket, Prefix=''form1/'', Delimiter="/") sections = [x[''Prefix''] for x in resp[''CommonPrefixes'']]

obtenemos:

form1/section11/ form1/section12/