현재 s3구조다.
python boto3로 디렉터리를 다운받는 코드를 짰다.
https://stackoverflow.com/questions/8659382/downloading-an-entire-s3-bucket 를 보면 콘솔로 자동으로 다운로드하는 방법이 나와있다. 구조가 위처럼 좀 복잡하고, 파일 하나당 크기가 크고, 하나 다운받고 하나 처리하는 방식으로 갈거여서 (사실 boto3를 이용하는게 조금 더 많이 익숙해서, aws configure를 서버에 설정하기 싫어서, 다운로드시 어떻게 동작할지 테스트하기 귀찮아서..) 짰다.
https://stackoverflow.com/questions/31918960/boto3-to-download-all-files-from-a-s3-bucket/31929277 에 보면 예시가 잘 나와있다.
아래에 좋은 지식적 답변도 하나있는데, s3에는 폴더라는게 없다고 한다. 파일 하나의 구조인데 파일 이름이 /로 구분되어서 폴더처럼 보이는거라고 한다. s3에서 보여줄때도 폴더처럼 보여주는게 더 좋아서 그렇게 보여주는듯싶고.
기본적으로 s3에서 폴더를 다운받으려면 아래 메소드를 쓴다.
s3 = boto3.client('s3', aws_access_key_id=access_key, aws_secret_access_key=secret_access_key ) s3.download_file(bucket_name, _from, _to) # _from은 위 s3사진의 구조로 예시를 들면 '폴더구조1/폴더구조2/폴더구조3/_SUCCESS', # _to는 내 로컬에서 저장할 위치이다.
그리고 s3에서 디렉터리 리스팅을 하려면 아래와 같다.
s3.get_paginator('list_objects').paginate(Bucket=self.bucket_name, Delimiter='/', Prefix='s3에서 시작할 파일 위치') # 나는 폴더구조2에서 시작할거였으므로 '폴더구조1/폴더구조2/' 를 입력해줬다. # Prefix작성시 끝에 /붙이는걸 잊지말자. for dir_list in self.s3.get_paginator('list_objects').paginate(Bucket= self.bucket_name, Delimiter='/', Prefix=s3_dir_path): print dir_list
디렉터리 리스팅을 하면 PageIterator 객체가 리턴되는데 결과를 보려면 하나하나 빼서 봐야 한다. dir_list를 출력해보면 사전이 하나 나오는데, 여기서 'CommonPrefixes'키가 있으면 디렉터리 안에 또다른 디렉터리가 있는거고, 'Contents'키가 있으면 디렉터리가 아니라 파일이라는 뜻인것 같다.(내가 테스트해본 결과)
내 구조는 폴더 안에 폴더가 있고, leaf에는 폴더가 없고 파일만 있다. 위의 특성을 이용하여 아래와 같이 짰다.
# -*- coding: utf-8 -*- import boto3 import os class AwsS3Manager: def __init__(self): self.access_key = '엑세스 키' self.secret_access_key = '시크릿 엑세스 키' self.s3 = boto3.client('s3', aws_access_key_id=self.access_key, aws_secret_access_key=self.secret_access_key ) self.bucket_name = '버킷 네임' def make_dir(self, path): if not os.path.exists(path): os.mkdir('./' + path) def download_file_from_s3(self, _from, _to): print "download file from s3 '{}' to local '{}'".format(_from, _to) if not os.path.exists(_to): self.s3.download_file(self.bucket_name, _from, _to) def download_folder_from_s3_recursively(self, s3_dir_path): for dir_list in self.s3.get_paginator('list_objects').paginate(Bucket=self.bucket_name, Delimiter='/', Prefix=s3_dir_path): # s3_dir_path에서 폴더나 파일을 찾는다. if 'CommonPrefixes' in dir_list: # 폴더가있으면.. for i, each_dir in enumerate(dir_list['CommonPrefixes']): # 폴더를 iteration한다. print 'start dir {}/{} ing..'.format(i+1, len(dir_list['CommonPrefixes'])) # print 'dir =',each_dir['Prefix'] self.download_folder_from_s3_recursively(each_dir['Prefix']) # 폴더들의 Prefix를 이용하여 다시 recursive하게 함수를 호출한다. if 'Contents' in dir_list: # 폴더가 아니라 파일이 있다. for i, each_file in enumerate(dir_list['Contents']): # 파일을 iteration한다. if i % 50 == 0: print 'download file {}/{} ing..'.format(i+1, len(dir_list['Contents'])) myfolder, filename = each_file['Key'].split('/')[-2:] # 내 로컬에 저장할 폴더 이름은 s3의 폴더 이름과 같게 한다. 파일 이름도 그대로. myfolder = './' + myfolder self.make_dir(myfolder) self.download_file_from_s3(each_file['Key'], myfolder + '/' + filename) # 저장한다... awss3manager = AwsS3Manager() awss3manager.download_folder_from_s3_recursively('폴더구조1/폴더구조2/')
'data engineering' 카테고리의 다른 글
python으로 hive의 쿼리 자동화하기. (0) | 2019.03.13 |
---|---|
spark processing parquet file from s3 with pass credentials. (0) | 2019.02.17 |
hive external table, partitioning (0) | 2019.01.28 |
mongodb slow query check.(and kill slow query) (0) | 2018.12.06 |
mongodb 중복제거한 아이템 갯수 구하기. (aggregate) (0) | 2018.07.16 |