Estoy tratando de descargar 12,000 archivos desde el cubo s3 usando el cuaderno jupyter, que se estima que completará la descarga en 21 horas. Esto se debe a que cada archivo se descarga de uno en uno. ¿Podemos hacer varias descargas paralelas entre sí para acelerar el proceso?
Actualmente, estoy usando el siguiente código para descargar todos los archivos
### Get unique full-resolution image basenames images = df['full_resolution_image_basename'].unique() print(f'No. of unique full-resolution images: {len(images)}') ### Create a folder for full-resolution images images_dir = './images/' os.makedirs(images_dir, exist_ok=True) ### Download images images_str = "','".join(images) limiting_clause = f"CONTAINS(ARRAY['{images_str}'], full_resolution_image_basename)" _ = download_full_resolution_images(images_dir, limiting_clause=limiting_clause)Vea el código a continuación. Esto solo funcionará con python 3.6+, debido a la cadena f ( PEP 498 ). Use un método diferente de formato de cadena para versiones anteriores de python.
Proporcione la ruta de acceso relative_path , el nombre de bucket_name y las claves de objeto de s3_object_keys . Además, max_workers es opcional y, si no se proporciona, el número será un múltiplo de 5 veces el número de procesadores de la máquina.
La mayor parte del código para esta respuesta provino de una respuesta a ¿Cómo crear un generador asíncrono en Python? qué fuentes de este ejemplo documentado en la biblioteca.
import boto3 import os from concurrent import futures relative_path = './images' bucket_name = 'bucket_name' s3_object_keys = [] # List of S3 object keys max_workers = 5 abs_path = os.path.abspath(relative_path) s3 = boto3.client('s3') def fetch(key): file = f'{abs_path}/{key}' os.makedirs(file, exist_ok=True) with open(file, 'wb') as data: s3.download_fileobj(bucket_name, key, data) return file def fetch_all(keys): with futures.ThreadPoolExecutor(max_workers=5) as executor: future_to_key = {executor.submit(fetch, key): key for key in keys} print("All URLs submitted.") for future in futures.as_completed(future_to_key): key = future_to_key[future] exception = future.exception() if not exception: yield key, future.result() else: yield key, exception for key, result in fetch_all(S3_OBJECT_KEYS): print(f'key: {key} result: {result}')Gracias por esto. Tenía 9000 sobre imágenes JPEG que necesitaba descargar desde mi S3. Intenté incorporar esto directamente en mi Colab Pro, pero no pude hacerlo funcionar. Seguía recibiendo el error "Errno 21: es un directorio".
Tuve que agregar 2 cosas: 1) un makedir para crear el directorio que quiero y 2) usar mknod, en lugar de mkdir.
fetch_all es casi lo mismo: excepto una pequeña edición para que max_workers realmente surta efecto. s3c es solo mi boto3.client con mis claves y todo.
Mi tiempo de descarga pasó de más de 30 minutos a 5 minutos con 1000 trabajadores.
os.makedirs('/*some dir you want*/*prefix*') def fetch(key): file = f'{abs_path}/{key}' os.mknod(file, mode=384) with open(file, 'wb') as data: s3c.download_fileobj(bucket_name, key, data) return file def fetch_all(keys): with futures.ThreadPoolExecutor(max_workers=max_workers) as executor: future_to_key = {executor.submit(fetch, key): key for key in keys} print("All URLs submitted.") for future in futures.as_completed(future_to_key): key = future_to_key[future] exception = future.exception() if not exception: yield key, future.result() else: yield key, exception