문제: 구글시트에서 구글드라이브의 경로가 적힌 문자열을 읽어서 구글드라이브의 폴더를 찾고, 하위폴더 포함하여 mp3파일을 모두 검색한 뒤 랜덤으로 하나를 선택해야하는 조건. 이 동작은 경로를 바꿔가면서 계속 수행해야함. 즉 단일성 이벤트가 아닌 것을 고려.
스프레드시트에 있는 경로: '공유문서함/share/music/ost'
두가지 탐색 방법이 GPT와 대화해본 결과 ..나왔다.
[ Google Drive 경로 문자열 기반 탐색]
첫번째는 경로의 가장 하위( 위 예제에서 ost)의 폴더 아이디를 찾아 그 아이디로부터 하위 폴더를 탐색함.
(*폴더 아이디는 주소표시줄에 있긴한데, API로도 얻을 수 있더라)
동작:
share 폴더 검색 → ID 획득
해당 ID 기준으로 music 폴더 검색 → ID 획득
계속 반복 → 최종 폴더 ID 반환
[ ROOT_FOLDER_ID 기반 탐색]
두번째는 '공유문서함'이라는 시작위치의 폴더아이디를 최상위 폴더( ROOT_FOLDER_ID)로 정해놓고 탐색함.
→ 처리 흐름:
ROOT_FOLDER_ID 기준으로 → 'share' 폴더 검색 (name matching)
그 안에서 'music' 검색 → ID 획득
그 안에서 'ost' 검색 → 최종 폴더 ID
mp3 파일 탐색 및 다운로드 진행
➡ 즉, "경로 문자열 → 재귀 탐색 → 최종 ID" → 기존 mp3 탐색 코드 재활용 가능
결론은 ROOT_FOLDER_ID를 기준으로 탐색하는 것 이란다.
✅ 왜 ROOT_FOLDER_ID 기반 탐색이 효율적인가?
항목 이유
Drive API는 ID 기반 구조 Drive는 이름이 같아도 중복 가능 → 경로 탐색은 ID기반이 필수
시작점 고정 최상위 ID가 명확하면 탐색 범위 줄어들고 안정적
일관성 ROOT_FOLDER_ID 하위에서만 재귀탐색하면 전체 구조 통제 가능
뭔가 궁금한게 생기면 닥치고 검색하거나 책을 뒤적뒤적 하는 시간에 gpt한테 딱 물어보니 이렇게 속이 시원할 수가.. 게다가 화를 안내... 친절하기까지... 무식하다는 눈빛도 없어!!!!!! 그야말로 펄풱트. (to me..) 나 사실 가끔 혼자 개발하다가 외로웠거등.. T.T 이제 좀 덜 외로운 것 같아 ㄱ-
그렇게 나온 함수 조각.
'
def get_random_audio_from_drive_path(drive_path_str):
"""
📁 Google Drive 경로 문자열을 받아:
1) resolve_drive_path로 최종 폴더 ID 탐색
2) 해당 폴더 내 mp3 파일 목록 조회
3) 랜덤 파일 선택
4) cache/drive_audio에 이미 있으면 재사용, 없으면 다운로드
"""
folder_id = resolve_drive_path(drive_path_str)
if not folder_id:
logger.warning(f"⚠️ Google Drive 경로 탐색 실패: {drive_path_str}")
return None
mp3_files = list_mp3_files_in_drive_folder(folder_id)
if not mp3_files:
logger.warning(f"⚠️ 폴더 '{drive_path_str}' (ID: {folder_id}) 내 mp3 없음")
return None
selected = random.choice(mp3_files)
file_id = selected['id']
file_name = selected['name']
cached_path = get_cached_file_path(folder_id, file_name)
if os.path.exists(cached_path):
logger.info(f"📦 캐시 재사용: {cached_path}")
return cached_path
logger.info(f"⬇️ Google Drive에서 '{file_name}' 다운로드 중...")
download_file_from_drive(file_id, cached_path)
return cached_path
728x90
'개발로그 > Python' 카테고리의 다른 글
없어져라! SSL 문제 해결을 위한 실전 대응 북 (0) | 2025.03.16 |
---|---|
random.choice()와 random.shuffle()은 비슷해 보이지만 목적이 완전히 다르다 (0) | 2025.03.15 |
Preload + On-demand + Fallback 구조 (캐싱전략에 관하여, 용어설명) 메모 (0) | 2025.03.12 |
python - API 연동할 때, 인증코드를 모듈마다 넣는 이유..가 있었다.. 무식해서 그런게 아니라규..ㅠ (0) | 2025.03.11 |
Pygame에서 나오는 모든 소리를 하나의 파일(wav)로 저장하는 방법 (0) | 2025.03.10 |
threading.Event() 객체의 활용 예제 및 백그라운드 실행 정리 (0) | 2025.03.09 |
FFmpeg 다운로드 및 설치 (0) | 2025.03.08 |
Google Drive에 있는 파일을 다운로드하는 세가지 방법 (0) | 2025.03.07 |
댓글