Python 실행과 오류 위치
60분 안팎
학습 목표
인터프리터와 소스 파일의 관계를 확인합니다.
개념
왜 첫 실행을 재현해야 하는가
신입이 코드를 받으면 첫 과제는 기능을 많이 추가하는 일보다 받은 그대로 실행되는지 확인하는 일입니다. 독서 기록 프로그램도 Python 실행 파일, app.py 소스, data/sample.txt 자료가 함께 맞아야 제목이 나옵니다. 어떤 파일을 어떤 명령으로 실행했는지 모르면 오타를 고쳤어도 다른 사본의 결과를 볼 수 있습니다. 이번 레슨은 실행 환경을 기록하고 오류에서 실제 경로와 소스 줄을 찾습니다. 아직 쪽수 검증이나 사용자 입력은 추가하지 않습니다. 첫 제목을 읽는 작은 실행을 확실하게 만들고 다음 모듈의 출발점으로 삼습니다.
인터프리터와 소스의 관계
python3 app.py에서 python3는 셸이 찾아 실행하는 인터프리터이고 app.py는 그 프로그램에 전달한 소스 경로입니다. 파일 확장자는 관례이며 실행 내용은 소스에 적힌 문장으로 결정됩니다. Python은 실행 과정에서 소스를 분석하고 바이트코드 등 내부 실행 형태를 사용합니다. 따라서 소스가 곧 CPU 기계 명령이라고 설명하지 않습니다. 이번 프로그램은 표준 라이브러리 pathlib만 사용하고 별도 패키지 설치가 필요 없습니다. 같은 소스를 다른 Python 설치본으로 실행할 수 있으므로 명령 이름뿐 아니라 실제 실행 경로도 확인합니다.
환경 기록에 무엇을 적는가
python3 --version으로 버전을 보고 command -v python3로 셸이 선택하는 명령을 확인합니다. Python 안에서는 sys.executable이 인터프리터 경로를 보여 줍니다. 실제 출력은 각자의 설치 위치에 따라 달라집니다. 강사의 버전과 경로를 복사해서 환경 확인 결과로 적지 않습니다. Python 3에서 실습하며 명령을 찾지 못하면 command not found가 나옵니다. 그 경우는 app.py의 문법 오류가 아니라 설치 또는 셸 검색 경로 문제입니다. 사용 중인 환경에서 Python 3 명령을 먼저 준비한 뒤 소스를 실행합니다. Windows WSL에서도 python3가 준비되어 있는지 확인합니다.
파일 경로 두 개를 분리한다
소스 파일 경로와 소스 안에서 읽을 자료 경로는 서로 다릅니다. python3 app.py를 실행할 때 app.py 자체가 없으면 인터프리터가 소스를 열지 못합니다. app.py는 있지만 내부 코드가 samples.txt를 요청하면 소스 실행 도중 FileNotFoundError가 납니다. 이 둘을 같은 오류라고 부르면 수정할 파일을 찾기 어렵습니다. 먼저 Python이 app.py를 열었는지, 그다음 자료를 읽는 줄까지 실행했는지 확인합니다. starter는 자료 이름에 불필요한 s가 들어 있으므로 실제 data/sample.txt와 철자를 비교해 고칩니다.
Traceback 읽는 순서
실행 중 예외가 발생하면 Traceback에는 호출 흐름과 파일 위치, 줄 번호가 표시됩니다. 마지막 줄에서 예외 종류와 설명을 먼저 읽습니다. FileNotFoundError라면 요청한 파일 경로를 찾아 실제 파일 목록과 비교합니다. 이어서 app.py에 해당하는 프레임을 찾아 그 줄의 코드를 확인합니다. 표준 라이브러리 내부 프레임이 보인다고 그 라이브러리 파일을 수정하지 않습니다. 경로를 전달한 자신의 소스가 원인일 수 있습니다. 긴 로그를 그대로 외우기보다 실패 종류·요청 대상·내 코드 위치를 세 칸으로 정리하면 다음 수정이 구체적으로 됩니다.
소스 위치를 기준으로 자료를 읽는다
Path(__file__).resolve().parent는 실행 중인 소스 파일의 위치를 바탕으로 부모 폴더를 얻습니다. 여기에 data와 sample.txt를 / 연산으로 연결하면 소스와 함께 배포된 자료를 찾을 수 있습니다. 이것은 문자열의 산술 나눗셈이 아니라 Path 객체의 경로 결합입니다. python3 /절대경로/app.py를 다른 작업 디렉터리에서 실행해도 같은 자료를 읽습니다. __file__은 이 스크립트 실행에서 제공되며 대화형 셸에서 그대로 쓸 수 있다고 가정하지 않습니다. 프로젝트에 묶인 입력 파일은 소스 위치 기준으로, 사용자가 넘기는 상대 경로는 별도 계약으로 정할 수 있습니다.
작게 고치고 다시 실행한다
이번 수정은 samples.txt를 sample.txt로 바꾸는 한 지점입니다. 제목을 print 안에 직접 넣으면 겉으로는 정답처럼 보이지만 실제 자료를 읽는 목표를 달성하지 못합니다. encoding="utf-8"과 read_text를 유지합니다. strip은 파일 끝의 줄바꿈과 양끝 공백을 제거한 문자열을 반환합니다. 지금 샘플에는 의미 있는 양끝 공백이 없으므로 한 줄 제목 출력에 사용합니다. 향후 제목의 공백 보존 정책이 필요해지면 요구사항에 맞게 따로 결정합니다. 수정 뒤 프로젝트 루트와 data 안에서 실행해 같은 제목인지 비교합니다.
다른 오류 메시지를 판단한다
SyntaxError는 소스를 분석하는 중 문법이 맞지 않는다는 신호입니다. 괄호나 따옴표가 닫혔는지 표시된 줄과 앞 줄을 확인합니다. NameError는 실행한 위치에서 사용한 이름을 찾지 못했다는 신호이므로 Path 임포트나 변수 철자를 봅니다. IndentationError는 블록 들여쓰기가 맞지 않다는 신호입니다. 이번 간단한 소스는 모든 문장이 맨 왼쪽에서 시작합니다. 오류 종류에 따라 수정 대상이 다르므로 파일을 못 찾았다는 문제에 Python을 다시 설치하는 식으로 범위를 넓히지 않습니다. 오류 위치를 좁히고 작은 변경 뒤 같은 명령을 다시 실행합니다.
검사와 인계의 완료 기준
bash check.sh는 프로젝트·data·외부 폴더에서 app.py를 실행하고 제목과 종료 코드를 확인합니다. 별도 구문 검사도 수행합니다. 시작 코드에서 일부 검사는 통과하지만 자료 경로 검사는 실패합니다. solution은 모두 통과해야 합니다. 검사가 끝나면 app.py, data/sample.txt, docs/runtime.md를 갖춘 미션을 완성합니다. 문서에는 실제 버전, 실행 방법, 경로 실패 원인과 수정, 메모리와 저장 파일 관찰을 적습니다. 다음 모듈은 이 구조 위에 제목과 쪽수 값의 계약을 추가합니다. 지금 단계에서는 종료 뒤 남는 파일과 실행 중 상태를 구분하고, 다른 사람이 같은 폴더에서 첫 제목을 재현할 수 있으면 충분합니다.
따라하기
실제 환경 기록
starter 압축을 푼 루트에서 실행하고 실제 버전과 인터프리터 경로를 메모합니다. 경로는 설치마다 달라 출력란을 비웁니다.
python3 --version
command -v python3
python3 -c "import sys; print(sys.executable)"실패 위치 확인
starter 루트에서 python3 app.py를 실행합니다. FileNotFoundError 마지막 줄의 samples.txt와 app.py 프레임을 찾습니다. pwd와 find로 실제 파일명이 sample.txt인지 확인합니다. 환경별 Traceback 경로는 출력란에 고정하지 않습니다.
python3 app.py
pwd
find . -type f -name "*.txt"같은 구조로 성공 실행
새 빈 연습 폴더에 demo.py로 저장해 실행합니다. app.py를 만드는 재현용 코드이므로 이미 작업한 미션 폴더에서는 실행하지 않습니다. 레슨 starter에서도 파일명을 수정한 뒤 python3 app.py와 bash check.sh로 확인합니다.
from pathlib import Path
import subprocess, sys
Path('data').mkdir(exist_ok=True)
Path('data/sample.txt').write_text('달빛 도서관\n', encoding='utf-8')
source = "from pathlib import Path\nsample = Path(__file__).resolve().parent / 'data' / 'sample.txt'\nprint(sample.read_text(encoding='utf-8').strip())\n"
Path('app.py').write_text(source, encoding='utf-8')
subprocess.run([sys.executable, 'app.py'], check=True)실행 결과
달빛 도서관
확인 문제
실습
app.py가 요청하는 자료명을 data/sample.txt와 맞춥니다. 소스 위치 기준 경로와 UTF-8 읽기를 유지하고 자료에서 읽은 제목을 출력합니다. starter의 README.md에서 실행 방법과 검사 대상을 확인합니다. tests/check.py와 check.sh는 변경하지 않습니다. 일부 검사가 실패하는 시작 상태를 확인한 뒤 수정하고 다시 검사합니다.
실행 명령
bash check.sh
기대 결과
모든 검사 줄이 PASS이며 마지막 줄은 ALL PASS, 종료 코드는 0입니다.
모범 답안
모범 답안 내려받기더 읽기
면접 질문
- 파일 경로 때문에 실행이 실패했을 때 확인 순서를 설명합니다.