HOWTO · Python
Python에서 다른 디렉토리의 파일 열기
현재 작업 디렉토리 밖의 파일을 절대 경로, pathlib 또는 상대 경로로 여는 방법과 경로가 해석되는 기준을 알아봅니다.
이 페이지의 내용
파일 경로를 Python의 open() 함수에 전달하면 됩니다. 절대 경로는 파일 시스템의 루트부터 파일 위치를 지정하고, 상대 경로는 프로세스의 현재 작업 디렉토리(CWD)를 기준으로 시작합니다. CWD는 스크립트가 들어 있는 디렉토리와 다를 수 있습니다. 프로젝트 파일의 경로를 만들 때는 pathlib.Path를 사용하면 운영 체제에 따른 차이를 간편하게 처리할 수 있습니다.
파일 경로와 현재 작업 디렉토리 이해하기
CWD는 Python이 상대 경로를 해석할 때 기준으로 삼는 디렉토리입니다. 보통 스크립트가 있는 디렉토리가 아니라 프로그램을 실행한 위치입니다. 경로가 예상한 위치를 가리키지 않는다면 먼저 CWD를 확인하세요.
import os
print(os.getcwd())
절대 경로는 CWD와 관계없이 위치를 지정합니다. data/notes.txt 같은 상대 경로는 CWD 아래의 경로로 해석됩니다. open()이 해당 위치에서 파일을 찾지 못하면 Python은 FileNotFoundError를 발생시킵니다. 코드를 바꾸기 전에 경로와 CWD가 모두 맞는지 확인하세요.
절대 경로로 파일 열기
파일의 위치를 알고 있다면 전체 경로를 사용하세요. 다음 예제는 임시 절대 경로에 파일을 만든 뒤 읽어서 내용을 출력합니다.
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
file_path = Path(directory) / "notes.txt"
file_path.write_text("Meeting at 10", encoding="utf-8")
with open(file_path, "r", encoding="utf-8") as file:
print(file.read())
임시 디렉토리를 사용하므로 컴퓨터에 이미 파일이 있는지 여부에 영향을 받지 않습니다. 실제 프로그램에서는 해당 파일의 실제 위치로 경로를 바꾸세요. "r" 모드는 텍스트를 읽으며, encoding="utf-8"은 문자 인코딩을 명시합니다. with 문은 블록이 끝날 때 파일을 닫으므로 블록 안에서 오류가 발생하더라도 파일이 닫힙니다.
Windows 경로는 슬래시(/)를 사용하거나 r"C:\Users\Ada\notes.txt" 같은 원시 문자열, 또는 "C:\\Users\\Ada\\notes.txt"처럼 백슬래시를 이스케이프한 문자열로 쓸 수 있습니다. 백슬래시 뒤에 인식되는 이스케이프 시퀀스가 올 때에만 백슬래시가 이스케이프를 시작합니다. 예를 들어 \n은 줄바꿈을 나타냅니다. 원시 문자열 리터럴은 백슬래시 하나로 끝날 수 없습니다. pathlib으로 경로 구성 요소를 결합하면 이러한 문자열 표기 문제를 상당 부분 피할 수 있습니다.
pathlib으로 경로 만들기
pathlib.Path는 파일 시스템 경로를 표현하고 결합하는 클래스입니다. / 연산자는 현재 운영 체제의 경로 규칙에 따라 경로 구성 요소를 연결합니다. 다음 예제는 형제 디렉토리에 파일을 만든 다음 절대 경로로 엽니다.
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as parent:
root = Path(parent)
current = root / "app"
other = root / "shared"
current.mkdir()
other.mkdir()
target = other / "notes.txt"
target.write_text("Shared notes", encoding="utf-8")
file_path = target.resolve()
with open(file_path, "r", encoding="utf-8") as file:
print(file.read())
실제 프로젝트에서는 Path("/srv/project") / "data" / "notes.txt"처럼 기준 디렉토리에서 시작해 하위 이름을 차례로 추가하면 됩니다. 프로그램을 어디서 실행하더라도 같은 위치를 가리켜야 한다면 절대 경로를 시작점으로 사용하세요. Path.resolve()는 존재하는 대상의 절대 경로를 제공하므로 경로를 진단할 때 도움이 될 수 있습니다.
상대 경로를 사용하거나 작업 디렉토리 변경하기
프로젝트에 scripts/read_notes.py와 shared/notes.txt가 있고 CWD가 project/scripts라고 가정해 보겠습니다. 이 CWD에서 ../shared/notes.txt는 한 단계 위인 project로 이동한 다음 shared 안의 파일을 가리킵니다. 실행 위치가 정해져 있다면 편리하지만, 프로그램이 다른 CWD에서 시작하면 같은 상대 경로가 다른 위치를 가리킬 수 있습니다. 스크립트의 위치를 기준으로 프로젝트 경로를 만들려면 Path(__file__).resolve().parent를 사용하세요.
다음 실행 가능한 예제는 프로젝트 디렉토리 구조를 만들고 프로세스의 CWD를 project/scripts로 설정한 뒤, 컨텍스트 관리자를 사용해 형제 디렉토리의 파일을 읽습니다.
import os
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
project = Path(directory) / "project"
scripts = project / "scripts"
shared = project / "shared"
scripts.mkdir(parents=True)
shared.mkdir()
(shared / "notes.txt").write_text("Project notes", encoding="utf-8")
original_directory = os.getcwd()
try:
os.chdir(scripts)
with open("../shared/notes.txt", "r", encoding="utf-8") as file:
print(file.read())
finally:
os.chdir(original_directory)
이 상대 경로는 프로세스의 CWD를 기준으로 해석됩니다. 이 예제에서는 CWD를 project/scripts로 설정했으므로 소스 파일이 있는 디렉토리를 기준으로 해석하지 않습니다.
프로그램이 한 디렉토리 안의 여러 파일을 다룬다면 프로세스의 CWD를 바꾼 다음 짧은 상대 경로를 사용할 수 있습니다. 다음 예제는 디렉토리를 바꾸기 전에 입력 파일을 만들고, 작업 후 원래 CWD를 복원합니다.
import os
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
target = Path(directory) / "notes.txt"
target.write_text("Daily notes", encoding="utf-8")
original_directory = os.getcwd()
try:
os.chdir(directory)
with open("notes.txt", "r", encoding="utf-8") as file:
print(file.read())
finally:
os.chdir(original_directory)
os.chdir()는 프로세스 전체의 상태를 바꾸므로 프로그램의 다른 부분에서 상대 경로를 해석하는 기준도 바뀝니다. 이전 디렉토리를 복원하면 이 영향을 제한할 수 있습니다. 파일 하나만 열 때는 절대 경로나 pathlib 경로를 전달하는 편이 대체로 간단합니다. 그래도 파일에 접근하지 못한다면 위치뿐 아니라 프로세스에 해당 파일을 읽을 권한이 있는지도 확인하세요.