Python

[AWS]. S3 Bucket 에서 데이터 다운받기 (with Python)

Acdong 2023. 2. 15. 18:31
728x90

 

BackGround

 

로컬에서 다양한 데이터 및 인공지능 모델들을 사용하다 배포하려고할때.

전부 데이터를 서버에 옮겨야한다.  이런경우 보통 SCP 명령어를 사용하거나 정말 귀찮을때는 그냥 VS code에서

드래그 엔 드롭하는데 용량이 클수록 시간이 오래걸린다.

 

그래서 이번에 데이터 및 모델을 불러올때 해당 파일이 없을 경우 AWS S3에서 파일을 다운받는 방법을 알아봤다.

한 번 해놓으면 다음부터 옮길일 없음 반복적인 일은 자동화하는게 프로그래머의 자세


What is AWS S3 ?

S3는 워낙 유명한 AWS의 스토리지 서비스이다.

 

Amazon Simple Storage Service(Amazon S3)는 업계 최고의 확장성,

데이터 가용성, 보안 및 성능을 제공하는 객체 스토리지 서비스입니다. (라고함.)

 

좋은 서비스인건 알겠는데 비용이 항상 문제다. 비용은 얼마나 들까?

 

50TB 이상 사용할 일은 없을테니 GB당 0.023 USD 라고 생각하면 되겠다.

 

가장 큰 데이터 셋의 크기가 3GB 쯤 되는데 100원정도 금액이 지불되겠다.

**S3는 사용할때만 비용이 청구된다.


How do I download from the S3 bucket?

Environment

Python3.9
Ubuntu20.04

 

1. Config 정의

from pydantic import BaseSettings
from typing import Optional

# configs.py
from pathlib import Path


class DbConfig(BaseSettings):

    BASE_DIR: Path = Path(__file__).resolve().parent
    DATA_PATH: Path = BASE_DIR.joinpath(
        "data/multi_unique_n7658745.gzip")

    S3_BUCKET_NAME: Optional[str] = None
    S3_ACCESS_KEY: Optional[str] = None
    S3_SECRET_KEY: Optional[str] = None

    class Config:
        env_file: str = ".env"


settings = DbConfig()

 

2. 다운로드 함수 선언

import boto3
import os
import sys

from config import settings


S3_ACCESS_KEY = settings.S3_ACCESS_KEY
S3_SECRET_KEY = settings.S3_SECRET_KEY
S3_BUCKET_NAME = settings.S3_BUCKET_NAME

DATA_PATH = settings.DATA_PATH
BASE_DIR = settings.BASE_DIR

def get_s3_client():
    s3 = boto3.client('s3',
                      aws_access_key_id=S3_ACCESS_KEY,
                      aws_secret_access_key=S3_SECRET_KEY,
                      region_name='ap-northeast-2'
                      )
    return s3


def download(local_file_name, s3_bucket, s3_object_key):
    s3 = get_s3_client()
    meta_data = s3.head_object(Bucket=s3_bucket, Key=s3_object_key)
    total_length = int(meta_data.get('ContentLength', 0))
    downloaded = 0

    def progress(chunk):
        nonlocal downloaded
        downloaded += chunk
        done = int(50 * downloaded / total_length)
        sys.stdout.write("\r[%s%s]" % ('=' * done, ' ' * (50-done)))
        sys.stdout.flush()

    print(f'Downloading {s3_object_key}')
    with open(local_file_name, 'wb') as f:
        s3.download_fileobj(
            s3_bucket, s3_object_key, f, Callback=progress)


def download_from_s3():
    if not os.path.exists(os.path.join(BASE_DIR, "data")):
        os.makedirs(os.path.join(BASE_DIR, "data"))
        print("download answer dataframe")
        download(DATA_PATH, S3_BUCKET_NAME,
                 'data/multi_unique_n7658745.gzip')
    else:
        print("answer dataframe already exists")

    print("upload setting complete")

그냥 다운로드를 해도 되지만 나는 Progress Bar 가 나오도록 설계했다 ( Ref 참조 )

 

2. 데이터 불러오기 전 추가하기

import pandas as pd

def _load_data():
    download_from_s3()
    df = pd.read_parquet(DATA_PATH)
    return df

 

 


Conclusion

이제 매번 데이터 및 모델이 바뀔때마다 직접 파일을 서버에 옮겨주지않아도 S3 Bucket에 등록해둔 파일을 없으면 다운받도록 설계했다. 귀찮이즘이 역시 기술발전의 원천이다.

NLP 모델의 경우는 HuggingFace에서 다운받아서 쓰는게 더 좋다고 생각하지만

크기가 큰 모델이나 데이터 셋의 경우는 비용이 아깝지만 ㅠㅠ S3에서 다운받아서 사용해도 좋을 것 같다.

 

 

Reference

https://stackoverflow.com/questions/50100221/download-file-from-aws-s3-using-python
https://stackoverflow.com/questions/41827963/track-download-progress-of-s3-file-using-boto3-and-callbacks
https://aws.amazon.com/ko/s3/pricing/

 

 

 

반응형