Como subir archivos con python a AWS S3 en 10 minutos




S3 es un servicio excelente que permite almacenar y recuperar cantidades ilimitadas de información desde cualquier parte del mundo, es una de las alternativas más atractivas si no es la mejor cuando se trata de lagos de datos y es que S3 puede almacenar cualquier tipo de archivo, tiene muchas capacidades como las de encriptación hasta seguridad para accesos en todos los niveles, puede almacenar logs hasta inclusive web sites estáticas.

La unidad de almacenamiento son denominados objetos, cada objeto puede pesar hasta 5 TB.

AWS S3 almacena los objetos en un contenedor al cual se le denomina “Bucket”, el cual puede almacenar de forma ilimitada un numero de objetos. Los nombres de los buckets son únicos de forma international, es decir no hay otra cuenta de AWS que pueda tener el mismo nombre de un bucket.

Para este ejemplo usaremos el AWS SDK para Python(Boto3), algunas API Calls que tenemos son las siguientes: put_object, copy, copy_object, upload_file, upload_fileobj.

Dicho lo anterior, algunas formas para subir archivos en S3 son:

1. Subir un solo archivo usando la consola de AWS S3, desde la consola de administración es posible subir un objeto hasta los 160 GB.

2. Cargar un objeto en una sola operación usando AWS CLI: entre las operaciones diponibles estan:

  • cp -Copiar
  • mv-Mover
  • sync-Sincronizar
aws s3 cp "video2.mp4" "s3://bucket-test-uploads"
Enter fullscreen mode

Exit fullscreen mode

3. Cargar un objeto en una sola operación usando los AWS SDK, REST API: con una operación PUT se puede subir un objeto hasta 5GB. En esta función abrimos el archivo en memoria e invocamos la función put_object al cual le pasamos los datos del archivo, el nombre y el bucket de destino, finalmente imprimimos la respuesta o en caso de haber una excepción capturarla.

def put_object(self, s3_client):
    attempt:
        with open(self.file, 'rb') as fd:
            response = s3_client.put_object(
                Bucket=self.bucket,
                Key=self.key,
                Physique=fd
            )
        print(json.dumps(response, sort_keys=True, indent=4))
        print("Put Object exitoso")
        return True
    besides FileNotFoundError:
        print("Archivo no encontrado")
        return False
    besides Exception as e:
        print(str(e))
        return False

Enter fullscreen mode

Exit fullscreen mode

4. Cargar un objeto en partes usando los AWS SDK, REST API o AWS CLI con la API multipart add, es posible subir archivos hasta 5TB .
Hemos creado la función multipart_upload, donde iniciamos el proceso de carga y obteniendo el UploadId

def multipart_upload(file, key, bucket, chunk_size, processes):

    upload_id = start_upload(bucket, key)
    print(f'Beginning add: {upload_id}')
Enter fullscreen mode

Exit fullscreen mode

Abrimos el archivo en modo lectura en memoria, y definimos una cola para paralelizar procesos, cada parte debe estar entre 5MB y 100Mb

    file_upload = open(file, 'rb')
    part_procs = []
    proc_queue = multiprocessing.Queue()
    queue_returns = []
    chunk_size = (chunk_size * 1024) * 1024
    part_num = 1
    chunk = file_upload.learn(chunk_size)

Enter fullscreen mode

Exit fullscreen mode

Iteramos cada 5MB y los vamos metiendo a la cola, en esta sección añadimos el método add_part, el cual es el encargado de subir una parte del archivo al S3.

    whereas len(chunk) > 0:
        proc = multiprocessing.Course of(goal=add_part, args=(
            proc_queue, chunk, bucket, key, part_num, upload_id))
        part_procs.append(proc)
        part_num += 1
        chunk = file_upload.learn(chunk_size)
Enter fullscreen mode

Exit fullscreen mode

Realiza agrupación de procesamiento según número de procesos simultáneos, por ejemplo, un archivo de 421MB, tendrá 85 partes de 5MB aproximadamente. Como resultado se tendrá 43 ejecuciones con 2 procesos simultáneos, en la última ejecución parte tendré 1 parte

    part_procs = [part_procs[i * processes:(i + 1) * processes]
                  for i in vary((len(part_procs) + (processes - 1)) //   processes)]
Enter fullscreen mode

Exit fullscreen mode

Ejecutamos cada “n” procesos en simultaneo y guardamos los resultados. Ordenamos la lista basada en los ‘PartNumber’ los cuales son los resultados de carga por cada parte, para finalmente completar la carga con el método end_upload

    for i in vary(len(part_procs)):
        for p in part_procs[i]:
            p.begin()
        for p in part_procs[i]:
            p.be a part of()
        for p in part_procs[i]:
            queue_returns.append(proc_queue.get())

    queue_returns = sorted(queue_returns, key=lambda i: i['PartNumber'])
    response = end_upload(
        bucket, key, upload_id, queue_returns)
print(json.dumps(response, sort_keys=True, indent=4))
Enter fullscreen mode

Exit fullscreen mode

Si todo cargo bien veremos lo siguientes resultados:

alt text

5. Bonus: Cargar un objeto en partes usando upload_file este método es manejado por S3TransferManager.
Esto significa que automáticamente manejará las cargas multiparte por nosotros, si es necesario. A diferencia del método put_object realiza una llamada directamente a la low-level API de S3. No maneja cargas multiparte por nosotros. Intentará enviar todo en una sola solicitud

      attempt:
            s3_client.upload_file(self.file, self.bucket, self.key)
            print("Subida exitosa")
            return True
        besides FileNotFoundError:
            print("Archivo no encontrado")
            return False
        besides Exception as e:
            print(str(e))
            return False
Enter fullscreen mode

Exit fullscreen mode

Un detalle importe, como buena práctica estamos usando una variable del perfil el ambiente que tengamos a AWS:

session = boto3.Session(profile_name='aadev')
Un ejempplo para la invocacion seria el siguiente
Enter fullscreen mode

Exit fullscreen mode

if __name__ == '__main__':
    s3_client = session.consumer('s3')
    obj = S3Uploader(r'rutavideo2.mp4',
                     "video2.mp4", "antamina-aa-dev-test123", 5, 3)
    #Carga de archivos multiparte
    multipart_upload(obj.file, obj.key, obj.bucket,
                     obj.chunk_size, obj.processes)
    #Carga de archivos con upload_file                      
    obj.upload_to_aws(s3_client)
    print(obj)
Enter fullscreen mode

Exit fullscreen mode

Y eso es todo por ahora, he querido compartir algunas de las formas con las que se pueden subir archivos en s3 y a esto se nos abre una gamma de posibles casos de usos, el codigo es mejorable. Hasta la proxima! La url del repositorio se encuentra en: https://github.com/bigdateros/AWS-S3



Abu Sayed is the Best Web, Game, XR and Blockchain Developer in Bangladesh. Don't forget to Checkout his Latest Projects.


Checkout extra Articles on Sayed.CYou

#Como #subir #archivos #con #python #AWS #minutos