코드 리뷰 중에 glob.glob을 이용하여 파일 리스트를 간편하게 가져오는 것을 봤다. 그동안 딥러닝에서 데이터 로더를 구현할 때 os.walk를 사용해 왔기에, glob.glob의 특징과 차이점에 대해 궁금해졌다. 더불어, 데이터 로더를 구성하는 데 있어 어느 방법이 더 효율적인지 함께 알아보고 싶었다.

glob.glob

glob.glob은 파이썬의 glob 모듈에 포함된 함수로, 주어진 패턴에 일치하는 모든 경로명을 찾아 리스트로 반환한다. 이 함수는 유닉스 셸 규칙을 사용하여 파일 이름을 패턴 매칭으로 필터링하는데, 예를 들어 *.txt는 모든 텍스트 파일을, data/*/train/*.jpg는 data 폴더의 모든 하위 폴더 내 train 폴더에 있는 모든 JPG 파일을 찾는 데 사용할 수 있다.

사용법

glob은 와일드카드 문자를 사용하여 복잡한 패턴도 매칭할 수 있다.

import glob
file_list = glob.glob('/path/to/folder/*.txt')  # 특정 폴더 내 모든 .txt 파일을 리스트로 반환

recursive=True 옵션을 사용하면 지정된 디렉터리의 모든 하위 디렉터리를 재귀적으로 탐색한다.

file_list = glob.glob('/path/to/folder/**/*.txt', recursive=True)  # 모든 하위 폴더 포함, .txt 파일 검색

dataloader에서 glob.glob 사용 시 장단점

장점

  1. 간단하고 쉬운 사용법 : 복잡한 디렉토리 구조에서도 손쉽게 파일을 검색할 수 있다.
  2. 패턴 매칭 : 다양한 패턴 매칭 옵션을 사용하여 필요한 파일만 선택적으로 로드할 수 있다.
  3. 플랫폼 독립적 : 다양한 운영 체제에서 일관된 방식으로 작동하여, 코드의 이식성을 높여준다.

단점

  1. 비효율적인 파일 처리 : 큰 디렉토리나 많은 파일이 있는 경우, 모든 파일 목록을 메모리에 한 번에 로드하기 때문에 성능 저하가 있을 수 있다.
  2. 정렬되지 않은 결과 : 반환된 파일 리스트가 파일 시스템에 따라 다른 순서로 정렬될 수 있다.

효율적인 검색 방법

대규모 파일 시스템에서 glob.glob의 단점을 보완할 수 있는 더 효율적인 파일 검색 방법은 여러 가지가 있다. 검색 속도 및 메모리 사용을 최적화하며 복잡한 요구 사항을 처리할 수 있다.

  1. os.walk

    os.walk는 디렉토리 트리를 순회하면서 파일과 폴더 목록을 Generator 형태로 반환한다. 이는 대규모 파일 시스템에서 메모리 사용량을 줄이는 데 도움이 된다.
import os

for root, dirs, files in os.walk('/path/to/folder'):
    for file in files:
        if file.endswith('.txt'):
            print(os.path.join(root, file))
  1. scandir 사용

    파이썬 3.5 이상에서는 os.scandir() 함수를 사용할 수 있으며, os.walk보다 더 효율적으로 디렉터리 내의 항목을 순회한다. scandir은 각 항목에 대한 메타데이터 접근을 최적화하여 성능을 향상시킨다.
import os

def find_files(directory, pattern):
    with os.scandir(directory) as entries:
        for entry in entries:
            if entry.is_file() and entry.name.endswith(pattern):
                print(entry.path)
            elif entry.is_dir():
                find_files(entry.path, pattern)


find_files('파일 경로', '.png')
  1. pathlib 모듈 사용

    파이썬 3.4 이상에서는 pathlib 모듈이 도입되었으며 해당 모듈은 파일 시스템 경로를 객체 지향적으로 쉽게 다룰 수 있게 해 준다. Path.rglob 메서드는 glob.glob와 유사한 기능을 제공하면서, Path 객체의 이점을 활용할 수 있다.
from pathlib import Path

path = Path('/path/to/folder')
for file_path in path.rglob('*.txt'):
    print(file_path)

이 외에도 Python에서 제공하는 라이브러리 외에 다른 라이브러리를 사용해서 더 효율적으로 구현할 수 있다.

느낀 점

os.walk 이외에 os.scandir이라는 함수를 새로 알게 되어 나중에 dataloader를 구현할 때 사용해 볼 것 같다. 또한, 파일이 많지 않은 경우라면 glob.glob의 사용도 충분히 고려해 볼 것 같다.

 

 

참고자료

https://docs.python.org/ko/3/library/glob.html
https://docs.python.org/3/library/os.html
https://docs.python.org/ko/3/library/pathlib.html