[Python] 파일경로 불러오기 (절대경로,상대경로)
파이선으로 프로젝트를 만들면서
파일경로를 불러오는게 어려워서 정리.
내 질문 :
파이선에서 다른 경로에 있는 config 파일안의 경로 변수들의 값을 불러 오고 싶은데 경로를 어떻게 지정해야 할까? 예를들어 project/config/api_key.json project/main.py 가 있을때 main.py 안에서 api_key.json 안에 정의한 API KEY 변수들의 값을 호출하고 싶은데 어떻게 코드를 짜면될지 알려줘.
답변 :
다른 경로에 있는 파일을 불러와 사용하는 방법은 여러 가지가 있지만,
Python에서는 일반적으로 os 모듈과 파일 경로를 결합하거나,
configparser, json 등을 사용하여 처리할 수 있습니다.
아래는 api_key.json에 정의된 데이터를 main.py에서 불러오는 방법입니다.
1. api_key.json 예제 파일
{
"API_KEY": "your_api_key_here",
"API_SECRET": "your_api_secret_here"
}
2. main.py에서 api_key.json 불러오기
2-1. 경로 처리
main.py가 config 폴더의 api_key.json 파일을 참조하려면, 상대 경로나 절대 경로를 명확히 지정해야 합니다.
import os
import json
# 현재 파일 위치를 기준으로 config 경로 계산
current_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(current_dir, 'config', 'api_key.json')
# JSON 파일 로드
def load_api_keys():
try:
with open(config_path, 'r') as file:
data = json.load(file)
return data
except FileNotFoundError:
print("Error: API key file not found.")
return {}
except json.JSONDecodeError:
print("Error: Failed to parse API key file.")
return {}
# API Key 불러오기
if __name__ == "__main__":
api_keys = load_api_keys()
print("API_KEY:", api_keys.get("API_KEY"))
print("API_SECRET:", api_keys.get("API_SECRET"))
3. 주요 포인트
- os.path 사용:
- os.path.dirname(__file__): 현재 실행 중인 스크립트의 디렉토리를 가져옵니다.
- os.path.join: 경로를 결합하여 OS에 따라 올바른 형식의 경로를 생성합니다.
- JSON 파일 파싱:
- json.load를 사용하여 파일 내용을 Python 딕셔너리로 변환합니다.
- 파일이 없거나 잘못된 JSON 파일일 경우 오류 처리를 추가합니다.
- 상대 경로 기반 처리:
- main.py 파일이 어느 경로에서 실행되든 항상 config/api_key.json을 올바르게 참조할 수 있도록 코드가 작성되었습니다.
4. 실행 결과
위 코드를 실행하면 다음과 같이 출력됩니다:
API_KEY: your_api_key_here
API_SECRET: your_api_secret_here
내 질문:
project/test/check_file_path.py 라는 파일에서 config/api_key.json 파일을 호출하고 싶은데 그러면 # 현재 파일 위치를 기준으로 config 경로 계산 current_dir = os.path.dirname(os.path.abspath(__file__)) config_path = os.path.join(current_dir, 'config', 'api_key.json') 이렇게 사용하면 파일을 못읽어 오는거 같은데 왜그런거야?
답변 :
check_file_path.py가 project/test/ 폴더 안에 있기 때문에,
**current_dir**은 test/ 폴더를 기준으로 계산됩니다.
하지만 config/api_key.json은 project/config/ 폴더에 있기 때문에, 경로를 잘못 계산한 것입니다.
1. 문제 원인
다음 코드에서:
current_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(current_dir, 'config', 'api_key.json')
- current_dir는 check_file_path.py의 위치(project/test/)를 기준으로 설정됩니다.
- 따라서 config_path는 project/test/config/api_key.json을 찾으려고 하게 됩니다.
- 그러나 실제 파일은 project/config/api_key.json에 있으므로 파일을 찾을 수 없습니다.
2. 해결 방법
2-1. 프로젝트 루트를 기준으로 경로 계산
**os.path**를 활용하여 프로젝트의 루트를 기준으로 config 경로를 설정해야 합니다. 이를 위해 **os.path.dirname()**을 여러 번 사용해 상위 폴더로 이동할 수 있습니다.
import os
import json
# 상위 디렉토리로 이동하여 프로젝트 루트 계산
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(os.path.dirname(current_dir)) # 'project/'까지 이동
config_path = os.path.join(project_root, 'config', 'api_key.json')
# JSON 파일 로드
def load_api_keys():
try:
with open(config_path, 'r') as file:
data = json.load(file)
return data
except FileNotFoundError:
print("Error: API key file not found.")
return {}
except json.JSONDecodeError:
print("Error: Failed to parse API key file.")
return {}
# 테스트
if __name__ == "__main__":
api_keys = load_api_keys()
print("API_KEY:", api_keys.get("API_KEY"))
print("API_SECRET:", api_keys.get("API_SECRET"))
2-2. pathlib 사용 (더 직관적이고 깔끔한 방식)
Python 3.4 이상에서는 pathlib 모듈을 사용해 경로를 쉽게 조작할 수 있습니다.
from pathlib import Path
import json
# 프로젝트 루트 계산
current_file = Path(__file__).resolve()
project_root = current_file.parents[1] # 'project/'까지 이동
config_path = project_root / 'config' / 'api_key.json'
# JSON 파일 로드
def load_api_keys():
try:
with open(config_path, 'r') as file:
data = json.load(file)
return data
except FileNotFoundError:
print("Error: API key file not found.")
return {}
except json.JSONDecodeError:
print("Error: Failed to parse API key file.")
return {}
# 테스트
if __name__ == "__main__":
api_keys = load_api_keys()
print("API_KEY:", api_keys.get("API_KEY"))
print("API_SECRET:", api_keys.get("API_SECRET"))
3. 중요한 포인트
- os.path vs pathlib:
- pathlib은 Python 3.4부터 추가된 모듈로, 객체 지향 방식으로 경로를 처리하여 더 직관적이고 유지보수하기 쉬움.
- os.path는 전통적인 방법으로, 여전히 유용하지만 조금 더 복잡하게 느껴질 수 있음.
- 프로젝트 루트 기준으로 작업:
- 파일 경로를 계산할 때 프로젝트 구조를 고려해야 합니다.
- os.path.dirname() 또는 Path.parents[]를 사용하여 상위 폴더를 정확히 지정해야 합니다.
4. 실행 결과
이제 check_file_path.py에서 config/api_key.json 파일을 제대로 읽을 수 있습니다.
API_KEY: your_api_key_here
API_SECRET: your_api_secret_here
5. 추가 팁
- 프로젝트가 커지면 환경 변수 관리 도구인 dotenv 모듈을 사용할 수도 있습니다.
- 예를 들어, .env 파일에 API Key를 저장하고 python-dotenv를 활용해 로드할 수도 있습니다.
dotenv는 **환경 변수를 외부 파일(.env)**로 관리할 수 있도록 도와주는 라이브러리입니다. 보통 비밀번호, API 키 같은 민감한 데이터를 코드에 직접 작성하지 않고 .env 파일로 분리하여 관리합니다. 이를 통해 코드의 보안성과 유연성을 높일 수 있습니다.
1. python-dotenv 설치하기
먼저 dotenv 라이브러리를 설치해야 합니다.
pip install python-dotenv
2. .env 파일 생성하기
project/config/.env 파일을 생성하고, 필요한 값을 저장합니다.
예시: .env
API_KEY=your_api_key_here
API_SECRET=your_api_secret_here
DEBUG=True
3. main.py에서 환경 변수 불러오기
dotenv를 사용하여 .env 파일의 값을 가져옵니다.
예시: main.py
import os
from dotenv import load_dotenv
# .env 파일 경로 설정 및 로드
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
config_path = BASE_DIR / 'config' / '.env'
load_dotenv(config_path) # .env 파일 로드
# 환경 변수 읽기
api_key = os.getenv("API_KEY") # 환경 변수에서 API_KEY 가져오기
api_secret = os.getenv("API_SECRET")
debug_mode = os.getenv("DEBUG", "False") # 기본값 False
# 출력
if __name__ == "__main__":
print("API_KEY:", api_key)
print("API_SECRET:", api_secret)
print("DEBUG mode:", debug_mode)
4. 주요 포인트
- .env 파일 내용 불러오기:
- load_dotenv()로 .env 파일의 값을 환경 변수로 로드합니다.
- .env 파일은 기본적으로 현재 경로에 있어야 하지만, 위 코드처럼 경로를 명시적으로 지정할 수도 있습니다.
- os.getenv로 환경 변수 읽기:
- 환경 변수 이름을 os.getenv("변수명")으로 불러옵니다.
- .env 파일에서 로드되지 않은 변수나 없는 변수는 기본값을 지정할 수 있습니다. 예: os.getenv("DEBUG", "False").
- 보안성:
- .env 파일은 .gitignore에 추가해 Git에 올리지 않도록 해야 합니다.
5. .gitignore 설정하기
.env 파일이 Git에 노출되지 않도록 아래 내용을 프로젝트의 .gitignore 파일에 추가하세요.
예시: .gitignore
# 환경 변수 파일
config/.env
6. 실행 결과
위 코드를 실행하면 .env에 정의된 값을 출력합니다.
API_KEY: your_api_key_here
API_SECRET: your_api_secret_here
DEBUG mode: True
7. dotenv를 사용하는 이유
- 보안: 민감한 정보를 코드에 직접 작성하지 않아서 노출 위험을 줄임.
- 유연성: 환경별(개발, 테스트, 프로덕션)로 다른 설정 파일을 쉽게 적용할 수 있음.
- 가독성: 설정을 한곳에서 관리하므로 코드가 깔끔해짐.