컴퓨터과학 챕터 6 약 8분

Ch6. Python 기초 — 파일 입출력과 예외처리

O
OIYO 편집부 기여자
6/8

파일 입출력이란

프로그램이 종료되면 메모리에 저장된 데이터는 모두 사라집니다. **파일 입출력(File I/O)**을 통해 데이터를 파일로 저장하거나 파일에서 읽어올 수 있습니다.

파이썬의 파일 처리는 크게 세 단계로 이루어집니다:

  1. 파일 열기open()
  2. 읽기 또는 쓰기 — read/write 메서드
  3. 파일 닫기close()

open() 함수

파일_객체 = open(파일경로, 모드, encoding=인코딩)

파일 열기 모드

모드의미파일이 없으면
'r'읽기(기본값)오류 발생
'w'쓰기 (파일 덮어쓰기)새로 생성
'a'추가 쓰기 (파일 끝에 추가)새로 생성
'x'독점 생성 (이미 있으면 오류)새로 생성
'rb'이진(binary) 읽기오류 발생
'wb'이진(binary) 쓰기새로 생성
# 텍스트 파일 쓰기
f = open("hello.txt", "w", encoding="utf-8")
f.write("안녕하세요!\n")
f.write("파이썬 파일 입출력입니다.\n")
f.close()   # 반드시 닫아야 함!

with 문 — 자동으로 파일 닫기 (권장)

with 문을 사용하면 블록을 벗어날 때 자동으로 파일이 닫힙니다. close()를 깜빡하는 실수를 방지할 수 있어 강력히 권장됩니다.

with open("hello.txt", "w", encoding="utf-8") as f:
    f.write("안녕하세요!\n")
    f.write("파이썬 파일 입출력입니다.\n")
# with 블록을 벗어나면 자동으로 f.close() 호출

파일 읽기

read() — 전체 내용 읽기

with open("hello.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(content)

# 출력:
# 안녕하세요!
# 파이썬 파일 입출력입니다.

readline() — 한 줄씩 읽기

with open("hello.txt", "r", encoding="utf-8") as f:
    line1 = f.readline()   # 첫 번째 줄
    line2 = f.readline()   # 두 번째 줄
    print(repr(line1))     # '안녕하세요!\n'
    print(repr(line2))     # '파이썬 파일 입출력입니다.\n'

readlines() — 모든 줄을 리스트로

with open("hello.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()   # ['안녕하세요!\n', '파이썬 파일 입출력입니다.\n']
    for line in lines:
        print(line.strip())  # strip()으로 줄바꿈 제거

for 루프로 읽기 (가장 효율적)

with open("hello.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())

파일 쓰기

write() — 문자열 쓰기

with open("output.txt", "w", encoding="utf-8") as f:
    f.write("첫 번째 줄\n")
    f.write("두 번째 줄\n")
    f.write("세 번째 줄\n")

writelines() — 리스트의 각 요소 쓰기

lines = ["사과\n", "바나나\n", "딸기\n"]
with open("fruits.txt", "w", encoding="utf-8") as f:
    f.writelines(lines)

파일에 내용 추가 (‘a’ 모드)

# 기존 파일 내용 유지하면서 추가
with open("log.txt", "a", encoding="utf-8") as f:
    f.write("새로운 로그 항목\n")

CSV 파일 처리

CSV(Comma-Separated Values)는 데이터를 쉼표로 구분하는 텍스트 형식입니다.

import csv

# CSV 쓰기
header = ["이름", "나이", "도시"]
rows = [
    ["김철수", 25, "서울"],
    ["이영희", 30, "부산"],
    ["박민준", 22, "인천"],
]

with open("people.csv", "w", newline="", encoding="utf-8-sig") as f:
    writer = csv.writer(f)
    writer.writerow(header)
    writer.writerows(rows)

# CSV 읽기
with open("people.csv", "r", encoding="utf-8-sig") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['이름']} ({row['나이']}세) — {row['도시']}")

JSON 파일 처리

JSON은 웹 API와 설정 파일에서 널리 쓰이는 데이터 형식입니다.

import json

# 파이썬 딕셔너리 → JSON 파일
data = {
    "name": "홍길동",
    "age": 25,
    "hobbies": ["독서", "코딩", "운동"],
    "address": {"city": "서울", "zip": "04524"}
}

with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

# JSON 파일 → 파이썬 딕셔너리
with open("data.json", "r", encoding="utf-8") as f:
    loaded = json.load(f)
    print(loaded["name"])      # 홍길동
    print(loaded["hobbies"])   # ['독서', '코딩', '운동']

예외처리 (Exception Handling)

프로그램 실행 중 발생하는 오류를 **예외(Exception)**라고 합니다. 예외처리를 통해 오류가 발생해도 프로그램이 중단되지 않고 계속 실행되도록 할 수 있습니다.


주요 예외 종류

예외 이름발생 상황
ValueError올바르지 않은 값 (예: int("abc"))
TypeError올바르지 않은 타입 연산 (예: 1 + "a")
ZeroDivisionError0으로 나눌 때 (예: 5 / 0)
IndexError리스트 범위 벗어난 인덱스
KeyError딕셔너리에 없는 키 접근
FileNotFoundError파일을 찾을 수 없음
NameError정의되지 않은 변수 사용
AttributeError존재하지 않는 속성/메서드 접근
PermissionError파일 접근 권한 없음
RecursionError재귀 호출 깊이 초과

try-except 문

try:
    # 예외가 발생할 수 있는 코드
    위험한_코드
except 예외종류:
    # 예외 발생 시 실행할 코드
    처리_코드
# 기본 예외처리
try:
    num = int(input("숫자를 입력하세요: "))
    result = 10 / num
    print(f"결과: {result}")
except ValueError:
    print("오류: 숫자가 아닌 값을 입력했습니다.")
except ZeroDivisionError:
    print("오류: 0으로는 나눌 수 없습니다.")

여러 예외 처리

try:
    numbers = [1, 2, 3]
    index = int(input("인덱스 입력: "))
    print(numbers[index])
except ValueError:
    print("정수를 입력해야 합니다.")
except IndexError:
    print(f"인덱스 범위를 벗어났습니다. (0~{len(numbers)-1})")
except Exception as e:
    # 예상치 못한 모든 예외 처리
    print(f"알 수 없는 오류 발생: {e}")

else와 finally

try:
    코드
except 예외:
    예외_처리
else:
    # try 블록이 예외 없이 정상 실행됐을 때
    정상_처리
finally:
    # 예외 발생 여부와 관계없이 항상 실행
    정리_코드
def safe_divide(a, b):
    try:
        result = a / b
    except ZeroDivisionError:
        print("0으로 나눌 수 없습니다.")
        return None
    else:
        print("나눗셈 성공!")
        return result
    finally:
        print("나눗셈 시도 완료.")  # 항상 실행

print(safe_divide(10, 2))
print(safe_divide(10, 0))

출력:

나눗셈 성공!
나눗셈 시도 완료.
5.0
0으로 나눌 수 없습니다.
나눗셈 시도 완료.
None

예외 정보 활용

try:
    result = int("abc")
except ValueError as e:
    print(f"ValueError 발생: {e}")
    # 출력: ValueError 발생: invalid literal for int() with base 10: 'abc'

예외 발생시키기 — raise

직접 예외를 발생시킬 수 있습니다.

def set_age(age):
    if age < 0:
        raise ValueError(f"나이는 0 이상이어야 합니다. 입력값: {age}")
    if age > 150:
        raise ValueError(f"유효하지 않은 나이입니다. 입력값: {age}")
    return age

try:
    set_age(-5)
except ValueError as e:
    print(f"오류: {e}")

파일 처리 + 예외처리 결합

def read_file_safe(filename):
    """안전하게 파일을 읽는 함수"""
    try:
        with open(filename, "r", encoding="utf-8") as f:
            return f.read()
    except FileNotFoundError:
        print(f"오류: '{filename}' 파일을 찾을 수 없습니다.")
        return None
    except PermissionError:
        print(f"오류: '{filename}' 파일 읽기 권한이 없습니다.")
        return None
    except UnicodeDecodeError:
        print(f"오류: 인코딩 문제가 발생했습니다.")
        return None

content = read_file_safe("없는파일.txt")
if content is None:
    print("파일을 읽지 못했습니다.")

실전 예제 — 점수 파일 처리 프로그램

# score_processor.py
import json

def load_scores(filename):
    """점수 파일 읽기"""
    try:
        with open(filename, "r", encoding="utf-8") as f:
            return json.load(f)
    except FileNotFoundError:
        print(f"'{filename}' 파일이 없습니다. 빈 데이터로 시작합니다.")
        return {}

def save_scores(filename, data):
    """점수 파일 저장"""
    with open(filename, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
    print(f"'{filename}'에 저장 완료.")

def add_score(data, name, score):
    """점수 추가 (유효성 검사 포함)"""
    if not isinstance(score, (int, float)):
        raise TypeError("점수는 숫자여야 합니다.")
    if not 0 <= score <= 100:
        raise ValueError(f"점수는 0~100이어야 합니다. 입력: {score}")
    data[name] = score
    return data

# 실행
scores = load_scores("scores.json")

try:
    scores = add_score(scores, "홍길동", 85)
    scores = add_score(scores, "이순신", 92)
    scores = add_score(scores, "유관순", 78)
    save_scores("scores.json", scores)
except (TypeError, ValueError) as e:
    print(f"입력 오류: {e}")

학습 정리

항목핵심 내용
open()파일 열기. 모드: r/w/a/x/b
with자동 파일 닫기, 안전한 파일 처리
read()전체 읽기
readline()한 줄 읽기
readlines()전체를 줄 리스트로
write()문자열 쓰기
encoding한글 처리 시 utf-8 지정
try-except예외 발생 시 처리
finally예외 여부 무관 항상 실행
raise직접 예외 발생

실전 퀴즈 5문항

Q1. 파일을 열 때 'r''a' 모드의 차이를 설명하고, 기존 파일에 새 줄을 추가하려면 어떤 모드를 사용해야 하나요?

A1.

  • 'r' (read): 읽기 전용. 파일이 없으면 FileNotFoundError 발생.
  • 'a' (append): 추가 쓰기. 파일이 있으면 끝에 내용을 추가하고, 없으면 새로 생성. 기존 파일에 새 줄을 추가하려면 'a' 모드를 사용해야 합니다. 'w'는 기존 내용을 모두 지우고 덮어씁니다.

Q2. with open(...) 문법을 사용하는 이유는 무엇인가요?

A2. with 문을 사용하면 블록을 벗어날 때 자동으로 close()가 호출됩니다. 예외가 발생해도 파일이 확실히 닫히므로, f.close() 호출을 잊어버리는 실수를 방지하고 시스템 자원 누수를 막을 수 있습니다.


Q3. 다음 코드에서 finally 블록이 출력되는 경우를 모두 나열하세요.

try:
    x = int("abc")
    print("성공")
except ValueError:
    print("ValueError 발생")
finally:
    print("finally 실행")

A3. finally 블록은 항상 실행됩니다. 이 코드에서는 int("abc")에서 ValueError가 발생하므로 "성공"은 출력되지 않고, "ValueError 발생""finally 실행" 순서로 출력됩니다. finally는 예외 발생 여부와 무관하게 실행됩니다.


Q4. except Exception as e:를 사용하는 이유와 주의사항은 무엇인가요?

A4. Exception은 거의 모든 예외의 부모 클래스이므로, 예상치 못한 모든 예외를 한 번에 잡을 수 있습니다. as e를 통해 오류 메시지를 확인할 수 있습니다. 다만 남용은 금물 — 어떤 예외가 발생했는지 모른 채 넘어가면 버그를 숨길 수 있습니다. 예상 가능한 예외는 구체적으로(ValueError, FileNotFoundError 등), 마지막 안전망으로만 Exception을 사용하는 것이 좋습니다.


Q5. 한글이 포함된 파일을 읽고 쓸 때 어떤 인코딩을 지정해야 하나요? 그리고 Windows에서 Excel이 읽는 CSV를 만들 때 특별히 사용하는 인코딩은 무엇인가요?

A5.

  • 일반적으로 한글 파일 처리에는 encoding="utf-8" 을 사용합니다.
  • Windows Excel이 바로 열 수 있는 CSV를 만들 때는 encoding="utf-8-sig" 를 사용합니다. utf-8-sig는 BOM(Byte Order Mark)이 포함된 UTF-8로, Excel이 한글 인코딩을 올바르게 인식합니다.
O

OIYO 편집부

Content Editor

지식 인큐베이터이자 전문 콘텐츠 크리에이터. 경영, 경제, 법률 및 실생활에 유용한 실무/자격증 중심의 깊이 있는 정보를 연구하고 공유합니다.