본문 바로가기
Python

23. 파일 읽기/쓰기 - 데이터를 저장하자

by 샤나엘 2026. 2. 22.
반응형

파일 읽기/쓰기

23. 파일 읽기/쓰기 - 데이터를 저장하자

프로그램이 꺼지면 변수에 담아둔 데이터도 사라진다. 데이터를 영구적으로 보관하고 싶다면? 파일에 저장하면 된다. 파일 입출력은 실무에서 가장 자주 쓰는 기능 중 하나다.


open() 함수 - 파일 열기의 기본

파일을 다루려면 먼저 open() 함수로 파일을 열어야 한다.

파일객체 = open("파일이름", "모드")

파일 모드 종류

파일 모드 비교

모드 설명 파일 없을 때
"r" 읽기 (Read) 에러 발생
"w" 쓰기 (Write) — 기존 내용 삭제 새로 생성
"a" 추가 (Append) — 기존 내용 뒤에 추가 새로 생성
"x" 생성 (eXclusive) — 파일이 이미 있으면 에러 새로 생성

기본 모드는 "r" (읽기)이다. 생략하면 읽기 모드로 열린다.


파일 쓰기 - write()

기본 쓰기

f = open("hello.txt", "w")
f.write("안녕하세요!\n")
f.write("파이썬 파일 입출력입니다.\n")
f.close()  # 반드시 닫아줘야 한다!

write() 메서드로 문자열을 파일에 쓴다. 줄바꿈(\n)은 직접 넣어야 한다.

writelines()로 여러 줄 쓰기

lines = ["첫 번째 줄\n", "두 번째 줄\n", "세 번째 줄\n"]

f = open("multi.txt", "w")
f.writelines(lines)
f.close()

writelines()은 리스트의 각 요소를 이어붙여 쓴다. 줄바꿈은 자동으로 추가되지 않으므로 각 문자열에 \n을 포함시켜야 한다.

추가 모드 (append)

# 기존 파일 끝에 내용 추가
f = open("hello.txt", "a")
f.write("새로 추가된 내용!\n")
f.close()

"w" 모드와 달리 "a" 모드는 기존 내용을 보존하고 뒤에 이어 쓴다.


파일 읽기 - read(), readline(), readlines()

read() - 전체 읽기

f = open("hello.txt", "r")
content = f.read()    # 파일 전체를 문자열로
print(content)
f.close()

readline() - 한 줄씩 읽기

f = open("hello.txt", "r")
line1 = f.readline()  # 첫 번째 줄
line2 = f.readline()  # 두 번째 줄
print(line1, end="")
print(line2, end="")
f.close()

readlines() - 전체를 리스트로

f = open("hello.txt", "r")
lines = f.readlines()   # ["안녕하세요!\n", "파이썬 파일 입출력입니다.\n", ...]
print(lines)
f.close()

for 문으로 한 줄씩 읽기 (가장 많이 쓰는 방법)

f = open("hello.txt", "r")
for line in f:
    print(line, end="")   # 이미 \n이 포함되어 있으므로 end="" 사용
f.close()

with 문 - 파일을 안전하게 다루기

매번 close()를 호출하는 건 귀찮고, 실수로 빠뜨리면 문제가 생길 수 있다. with 문을 쓰면 자동으로 닫아준다.

# with 문을 사용하면 블록을 벗어나면 자동으로 close()
with open("hello.txt", "r") as f:
    content = f.read()
    print(content)
# 여기서 f는 이미 닫힘 — 걱정 없다!

with 문으로 쓰기

with open("output.txt", "w") as f:
    f.write("with 문으로 쓰기!\n")
    f.write("자동으로 닫아주니 편하다.\n")

실무에서는 거의 항상 with 문을 사용한다. 이유: 예외가 발생해도 파일이 안전하게 닫히기 때문이다.

with 문 비교

# 😐 옛날 방식
f = open("data.txt", "r")
try:
    content = f.read()
finally:
    f.close()

# 😊 with 문 (권장)
with open("data.txt", "r") as f:
    content = f.read()

실전 예시: 메모장 프로그램

def save_memo(filename, memo):
    """메모를 파일에 추가"""
    with open(filename, "a", encoding="utf-8") as f:
        f.write(memo + "\n")
    print("메모가 저장되었습니다!")

def read_memos(filename):
    """저장된 메모 전체 출력"""
    try:
        with open(filename, "r", encoding="utf-8") as f:
            content = f.read()
            if content:
                print("=== 저장된 메모 ===")
                print(content)
            else:
                print("저장된 메모가 없습니다.")
    except FileNotFoundError:
        print("아직 메모가 없습니다.")

# 사용 예
save_memo("memos.txt", "우유 사기")
save_memo("memos.txt", "파이썬 공부하기")
read_memos("memos.txt")

encoding="utf-8"을 지정하면 한글이 깨지지 않는다. Windows에서 특히 중요하다.


CSV 파일 다루기

CSV (Comma-Separated Values)는 데이터를 쉼표로 구분하는 파일 형식이다. 엑셀에서도 열 수 있어서 데이터 교환에 많이 쓰인다.

직접 읽기 (기본 방법)

# students.csv 파일 내용:
# 이름,국어,영어,수학
# 김철수,85,90,78
# 이영희,92,88,95
# 박민수,76,82,89

with open("students.csv", "r", encoding="utf-8") as f:
    for line in f:
        row = line.strip().split(",")
        print(row)
# ['이름', '국어', '영어', '수학']
# ['김철수', '85', '90', '78']
# ...

csv 모듈 사용하기

파이썬에는 CSV를 편하게 다루는 csv 모듈이 내장되어 있다.

import csv

# CSV 읽기
with open("students.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f)
    header = next(reader)       # 첫 줄(헤더) 건너뛰기
    print(f"과목: {header[1:]}")

    for row in reader:
        name = row[0]
        scores = [int(s) for s in row[1:]]
        avg = sum(scores) / len(scores)
        print(f"{name}: 평균 {avg:.1f}점")

csv.writer로 쓰기

import csv

students = [
    ["이름", "국어", "영어", "수학"],
    ["김철수", 85, 90, 78],
    ["이영희", 92, 88, 95],
    ["박민수", 76, 82, 89]
]

with open("result.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    for row in students:
        writer.writerow(row)    # 한 줄씩 쓰기

    # 또는 한번에: writer.writerows(students)

newline=""을 지정하지 않으면 Windows에서 빈 줄이 생길 수 있다.

csv.DictReader - 딕셔너리로 읽기

import csv

with open("students.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['이름']}: 국어 {row['국어']}, 영어 {row['영어']}")

DictReader는 첫 줄을 헤더(키)로 사용해서 각 행을 딕셔너리로 만들어준다. 컬럼 이름으로 접근할 수 있어서 훨씬 직관적이다.


파일 경로 다루기

상대 경로 vs 절대 경로

# 상대 경로 — 현재 작업 디렉토리 기준
open("data.txt", "r")
open("data/scores.csv", "r")

# 절대 경로 — 전체 경로
open("C:/Users/user/Documents/data.txt", "r")
open("/home/user/data.txt", "r")

os.path로 경로 다루기

import os

# 파일 존재 확인
if os.path.exists("data.txt"):
    print("파일이 있습니다!")

# 경로 합치기
path = os.path.join("data", "students.csv")
print(path)   # data/students.csv (OS에 맞게)

# 파일 이름만 추출
print(os.path.basename("/home/user/data.txt"))  # data.txt

# 폴더만 추출
print(os.path.dirname("/home/user/data.txt"))   # /home/user

직접 해보기

문제 1. 사용자로부터 이름과 나이를 입력받아 profiles.txt에 저장하는 코드를 작성해보자. 여러 번 실행해도 기존 내용이 유지되어야 한다.

문제 2. 파일에서 숫자를 읽어 합계와 평균을 계산하는 함수를 작성해보자. numbers.txt에 한 줄에 하나씩 숫자가 적혀 있다고 가정한다.

문제 3. 학생 성적 데이터를 CSV 파일에 저장하고, 다시 읽어서 평균 점수가 가장 높은 학생을 찾아보자.

문제 4. 텍스트 파일의 글자 수, 단어 수, 줄 수를 세는 count_file_stats(filename) 함수를 작성해보자.

정답 보기
# 문제 1 - 프로필 저장
name = input("이름: ")
age = input("나이: ")
‍
with open("profiles.txt", "a", encoding="utf-8") as f:
    f.write(f"{name}, {age}세\n")
‍
print("저장 완료!")
‍
# 저장된 내용 확인
with open("profiles.txt", "r", encoding="utf-8") as f:
    print(f.read())
‍
‍
# 문제 2 - 숫자 합계와 평균
def sum_and_avg(filename):
    with open(filename, "r") as f:
        numbers = []
        for line in f:
            line = line.strip()
            if line:
                numbers.append(float(line))
‍
    total = sum(numbers)
    avg = total / len(numbers) if numbers else 0
    return total, avg
‍
# numbers.txt에 10, 20, 30, 40, 50이 있다면
# total, avg = sum_and_avg("numbers.txt")
# print(f"합계: {total}, 평균: {avg}")
‍
‍
# 문제 3 - CSV 성적 관리
import csv
‍
# 저장
students = [
    ["이름", "국어", "영어", "수학"],
    ["김철수", 85, 90, 78],
    ["이영희", 92, 88, 95],
    ["박민수", 76, 82, 89]
]
‍
with open("scores.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(students)
‍
# 읽기 + 최고 성적 찾기
best_name = ""
best_avg = 0
‍
with open("scores.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        avg = (int(row["국어"]) + int(row["영어"]) + int(row["수학"])) / 3
        print(f"{row['이름']}: 평균 {avg:.1f}")
        if avg > best_avg:
            best_avg = avg
            best_name = row["이름"]
‍
print(f"\n최고 성적: {best_name} ({best_avg:.1f}점)")
‍
‍
# 문제 4 - 파일 통계
def count_file_stats(filename):
    with open(filename, "r", encoding="utf-8") as f:
        content = f.read()
‍
    chars = len(content)
    words = len(content.split())
    lines = content.count("\n") + (1 if content and not content.endswith("\n") else 0)
‍
    return chars, words, lines
‍
# 사용 예시
# c, w, l = count_file_stats("hello.txt")
# print(f"글자 수: {c}, 단어 수: {w}, 줄 수: {l}")

오늘의 정리

항목 내용
open() 파일 열기. 모드: "r" 읽기, "w" 쓰기, "a" 추가
with 문 with open() as f: — 자동으로 파일을 닫아줌 (권장)
읽기 메서드 read() 전체, readline() 한 줄, readlines() 리스트
쓰기 메서드 write() 문자열 쓰기, writelines() 리스트 쓰기
CSV 모듈 csv.reader, csv.writer, csv.DictReader로 CSV 파일 처리
encoding encoding="utf-8" 지정으로 한글 깨짐 방지

다음 편 예고: 정규표현식 - 문자열 처리의 끝판왕

이메일 형식이 맞는지, 전화번호에서 숫자만 뽑고 싶을 때, 특정 패턴의 텍스트를 한방에 찾고 싶을 때... 정규표현식이 그 해답이다!


태그: 파이썬 Python 파이썬독학 파일입출력 open read write with문 CSV 파이썬기초 IT교육

반응형

댓글