Summary
- 상대 경로는 터미널 실행 위치(CWD)에 따라 달라져
FileNotFoundError를 일으킨다Path(__file__).resolve().parent패턴은 파일 자체 위치를 기준으로 삼아 어디서 실행하든 흔들리지 않는다- 경로 결합은 슬래시(
/) 연산자로 하며 OS 구분은 pathlib가 알아서 처리한다
문제: 상대 경로의 배신
리소스 파일을 불러올 때 상대 경로를 쓰면 터미널 실행 위치에 따라 경로가 달라진다.
# 위험한 방식 — 터미널 실행 위치에 따라 경로가 달라짐
config_path = "./config/settings.yaml"이 코드는 main.py가 있는 폴더에서 실행하면 작동하지만, 다른 경로에서 실행하면 ./를 현재 작업 위치(CWD)로 인식해 파일을 찾지 못한다.
해결: pathlib의 황금 패턴
파일 자체의 위치를 기준으로 경로를 잡으면 실행 위치와 무관하게 안전하다.
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
PROMPT_DIR = BASE_DIR / "prompts"이 한 줄은 세 단계로 나뉜다.
| 코드 | 결과 | 설명 |
|---|---|---|
Path(__file__) | ./src/main.py | 현재 파일 경로(상대 경로일 수 있음) |
.resolve() | C:\Project\src\main.py | 디스크상의 절대 경로로 변환 |
.parent | C:\Project\src | 파일명을 떼고 부모 폴더만 남김 |
Path(__file__):__file__은 현재 실행 중인 파일의 경로를 담은 내장 변수다.Path()로 다루기 쉬운 객체로 만든다..resolve(): 경로를 절대 경로로 확정한다. 실행 환경에 따라 상대 경로로 인식될 수 있는__file__을 디스크상의 실제 전체 주소로 고정하며, 심볼릭 링크 문제도 해결한다..parent: 필요한 것은 파일이 아니라 기준 폴더이므로, 파일명을 떼어내고 부모 디렉토리만 남긴다.
활용
BASE_DIR을 기준으로 프로젝트 내 어떤 파일이든 안전하게 가리킬 수 있다. OS별 경로 구분(\ vs /)은 pathlib가 알아서 처리한다.
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
# 슬래시 연산자로 경로 결합
IMAGE_DIR = BASE_DIR / "data" / "images"
CONFIG_FILE = BASE_DIR / "config.json"
if not CONFIG_FILE.exists():
print(f"설정 파일을 찾을 수 없습니다: {CONFIG_FILE}")
else:
print(f"설정 파일 로드 완료: {CONFIG_FILE}")리소스 파일을 다룰 때는 os.path나 단순 문자열 경로 대신 pathlib의 .resolve().parent 패턴을 쓰는 것이 견고한 코드의 첫걸음이다.
Reference