メインコンテンツにスキップ

파일 입출력

Pythonで 파일을 읽고 쓰는 방법を学びましょう. 파일 입출력은 데이터를 저장하고 불러오는 가장 기본적인 작업입니다.

基本的なファイルの開き方

open() 함수

# 파일 열기
file = open('example.txt', 'r')
content = file.read()
file.close() # 반드시 닫아야 함

print(content)

파일 모드

모드설명
'r'읽기 모드 (기본값)
'w'쓰기 모드 (파일이 있으면 덮어씀)
'a'추가 모드 (파일 끝에 내용 추가)
'x'생성 모드 (파일이 없을 때만 생성)
'b'바이너리 모드 (예: 'rb', 'wb')
't'텍스트 모드 (기본값)
'+'읽기/쓰기 모드 (예: 'r+', 'w+')

with 문 사용하기 📋

파일을 자동으로 닫아주는 안전한 방법입니다.

# 권장하는 방법
with open('example.txt', 'r', encoding='utf-8') as file:
content = file.read()
print(content)
# with 블록을 벗어나면 자동으로 파일이 닫힘

ファイルの読み取り

전체 읽기

# 전체 내용을 문자열로 읽기
with open('data.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(content)

한 줄씩 읽기

# readline() - 한 줄씩 읽기
with open('data.txt', 'r', encoding='utf-8') as f:
line1 = f.readline() # 첫 번째 줄
line2 = f.readline() # 두 번째 줄
print(line1)
print(line2)

모든 줄을 리스트로 읽기

# readlines() - 모든 줄을 리스트로
with open('data.txt', 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
print(line.strip()) # 줄바꿈 문자 제거

반복문으로 읽기 (메모리 효율적)

# 파일 객체를 직접 반복 (큰 파일에 유용)
with open('large_file.txt', 'r', encoding='utf-8') as f:
for line in f:
print(line.strip())

ファイルへの書き込み

새로 쓰기 (덮어쓰기)

# 파일에 쓰기
with open('output.txt', 'w', encoding='utf-8') as f:
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')

바이너리 파일 다루기

이미지 파일 복사

# 바이너리 모드로 이미지 복사
with open('original.jpg', 'rb') as source:
with open('copy.jpg', 'wb') as target:
target.write(source.read())

바이트 단위로 읽기

# 일정 크기씩 읽기 (메모리 절약)
with open('large_file.bin', 'rb') as f:
chunk_size = 1024 # 1KB
while True:
chunk = f.read(chunk_size)
if not chunk:
break
# chunk 처리
print(f'읽은 바이트 수: {len(chunk)}')

경로 다루기 (pathlib) 🛤️

pathlib은 파일 경로를 객체지향적으로 다룰 수 있게 해줍니다.

from pathlib import Path

# 경로 객체 생성
path = Path('documents/report.txt')

# 경로 정보
print(path.name) # 'report.txt'
print(path.stem) # 'report'
print(path.suffix) # '.txt'
print(path.parent) # 'documents'

# 절대 경로
print(path.absolute())

# 경로 존재 여부
if path.exists():
print('파일이 존재합니다')

# 디렉토리 확인
if path.is_file():
print('파일입니다')
if path.is_dir():
print('디렉토리입니다')

pathlib으로 ファイルの読み取り/쓰기

from pathlib import Path

# ファイルの読み取り
path = Path('data.txt')
content = path.read_text(encoding='utf-8')

# ファイルへの書き込み
path.write_text('새로운 내용', encoding='utf-8')

# 바이너리
data = path.read_bytes()
path.write_bytes(b'binary data')

디렉토리 다루기

from pathlib import Path

# 디렉토리 생성
Path('new_folder').mkdir(exist_ok=True)

# 중첩 디렉토리 생성
Path('parent/child/grandchild').mkdir(parents=True, exist_ok=True)

# 디렉토리 내 파일 목록
for file in Path('.').glob('*.txt'):
print(file)

# 재귀적으로 모든 파일 찾기
for file in Path('.').rglob('*.py'):
print(file)

実践例 💡

예제 1: 로그 파일 파서

from datetime import datetime
from pathlib import Path

def parse_log_file(log_path):
"""로그 파일에서 에러만 추출"""
errors = []

with open(log_path, 'r', encoding='utf-8') as f:
for line in f:
if 'ERROR' in line:
errors.append(line.strip())

return errors

# 사용 예제
log_file = Path('app.log')
if log_file.exists():
errors = parse_log_file(log_file)

# 에러를 별도 파일로 저장
error_file = Path('errors.txt')
error_file.write_text('\n'.join(errors), encoding='utf-8')

print(f'총 {len(errors)}개의 에러 발견')

예제 2: 파일 백업

from pathlib import Path
from datetime import datetime
import shutil

def backup_file(file_path):
"""파일을 백업 (타임스탬프 포함)"""
path = Path(file_path)

if not path.exists():
print(f'파일이 존재하지 않습니다: {file_path}')
return None

# 백업 파일명 생성
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
backup_name = f'{path.stem}_{timestamp}{path.suffix}'
backup_path = path.parent / 'backups' / backup_name

# 백업 디렉토리 생성
backup_path.parent.mkdir(exist_ok=True)

# 파일 복사
shutil.copy2(path, backup_path)
print(f'백업 완료: {backup_path}')

return backup_path

# 사용 예제
backup_file('important_data.txt')

예제 3: CSV 파일 읽고 처리하기

from pathlib import Path

def process_csv_simple(csv_path):
"""간단한 CSV 파일 처리"""
with open(csv_path, 'r', encoding='utf-8') as f:
# 헤더 읽기
header = f.readline().strip().split(',')
print(f'컬럼: {header}')

# 데이터 읽기
for line in f:
values = line.strip().split(',')
data = dict(zip(header, values))
print(data)

# 사용 예제
# process_csv_simple('users.csv')

예제 4: 대용량 파일 처리

def process_large_file(file_path, chunk_size=8192):
"""대용량 파일을 청크 단위로 처리"""
total_bytes = 0

with open(file_path, 'rb') as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break

total_bytes += len(chunk)
# 청크 처리 로직

return total_bytes

# 사용 예제
# size = process_large_file('large_data.bin')
# print(f'처리한 크기: {size / (1024**2):.2f} MB')

예제 5: 설정 ファイルの読み取り/쓰기

from pathlib import Path

class ConfigManager:
"""간단한 설정 파일 관리자"""

def __init__(self, config_path='config.txt'):
self.path = Path(config_path)
self.config = {}
self.load()

def load(self):
"""설정 파일 로드"""
if not self.path.exists():
return

with open(self.path, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#'):
key, value = line.split('=', 1)
self.config[key.strip()] = value.strip()

def save(self):
"""설정 파일 저장"""
with open(self.path, 'w', encoding='utf-8') as f:
for key, value in self.config.items():
f.write(f'{key}={value}\n')

def get(self, key, default=None):
"""설정 값 가져오기"""
return self.config.get(key, default)

def set(self, key, value):
"""설정 값 설정하기"""
self.config[key] = value

# 사용 예제
config = ConfigManager()
config.set('app_name', 'MyApp')
config.set('version', '1.0.0')
config.save()

print(config.get('app_name')) # 'MyApp'

예제 6: 파일 정보 분석

from pathlib import Path
import os

def analyze_directory(dir_path):
"""디렉토리 분석 리포트"""
path = Path(dir_path)

if not path.is_dir():
print('디렉토리가 아닙니다')
return

total_files = 0
total_size = 0
file_types = {}

for file in path.rglob('*'):
if file.is_file():
total_files += 1
size = file.stat().st_size
total_size += size

# 확장자별 집계
ext = file.suffix or 'no extension'
if ext not in file_types:
file_types[ext] = {'count': 0, 'size': 0}
file_types[ext]['count'] += 1
file_types[ext]['size'] += size

# 리포트 출력
print(f'총 파일 수: {total_files}')
print(f'총 크기: {total_size / (1024**2):.2f} MB')
print('\n파일 타입별 통계:')
for ext, info in sorted(file_types.items()):
print(f' {ext}: {info["count"]}개, {info["size"] / 1024:.2f} KB')

# 사용 예제
# analyze_directory('.')

파일 위치 찾기 (커서)

with open('data.txt', 'r') as f:
print(f.tell()) # 현재 위치: 0

f.read(10) # 10바이트 읽기
print(f.tell()) # 현재 위치: 10

f.seek(0) # 처음으로 이동
print(f.tell()) # 현재 위치: 0

파일 인코딩 💭

# UTF-8 인코딩 (권장)
with open('한글.txt', 'w', encoding='utf-8') as f:
f.write('안녕하세요')

# 다른 인코딩으로 읽기
encodings = ['utf-8', 'cp949', 'euc-kr']
for enc in encodings:
try:
with open('한글.txt', 'r', encoding=enc) as f:
content = f.read()
print(f'{enc}: 성공')
break
except UnicodeDecodeError:
print(f'{enc}: 실패')

よくある質問 ❓

Q1: 파일이 열려 있는지 확인하는 방법은?

file = open('test.txt', 'r')
print(file.closed) # False

file.close()
print(file.closed) # True

Q2: 파일 존재 여부를 확인하는 방법은?

from pathlib import Path
import os

# 방법 1: pathlib
if Path('file.txt').exists():
print('파일이 존재합니다')

# 방법 2: os 모듈
if os.path.exists('file.txt'):
print('파일이 존재합니다')

Q3: 임시 파일을 만드는 방법은?

import tempfile

# 임시 파일 생성
with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as f:
f.write('임시 데이터')
temp_path = f.name
print(f'임시 파일: {temp_path}')

# 사용 후 삭제
Path(temp_path).unlink()

Q4: 파일을 안전하게 덮어쓰는 방법은?

from pathlib import Path
import shutil

def safe_write(file_path, content):
"""백업 후 ファイルへの書き込み"""
path = Path(file_path)

# 기존 파일 백업
if path.exists():
backup = path.with_suffix(path.suffix + '.bak')
shutil.copy2(path, backup)

try:
# 새 내용 쓰기
path.write_text(content, encoding='utf-8')
except Exception as e:
# 실패 시 백업 복원
if backup.exists():
shutil.copy2(backup, path)
raise e

Q5: 파일 크기를 확인하는 방법은?

from pathlib import Path

path = Path('file.txt')

# 방법 1: stat()
size = path.stat().st_size
print(f'크기: {size} bytes')

# 방법 2: os 모듈
import os
size = os.path.getsize('file.txt')
print(f'크기: {size} bytes')

주의사항 ⚠️

  1. 항상 인코딩 지정: encoding='utf-8'을 명시하세요
  2. with 문 사용: 파일이 자동으로 닫히도록 보장
  3. 대용량 파일: 한 번에 읽지 말고 청크 단위로 처리
  4. 경로 구분자: / 사용 또는 pathlib 사용 (Windows 호환성)
  5. 예외 처리: 파일이 없거나 권한이 없을 수 있음

성능 팁 🚀

# 좋음: 파일 객체 직접 반복 (메모리 효율적)
with open('large.txt', 'r') as f:
for line in f:
process(line)

# 나쁨: 전체를 메모리에 로드
with open('large.txt', 'r') as f:
for line in f.readlines(): # 모든 줄을 메모리에 로드
process(line)

次のステップ

  • 예외 처리: 파일 작업 중 발생하는 에러를 우아하게 처리하는 방법
  • JSON과 CSV: 구조화된 데이터 파일 형식 다루기
  • os와 shutil 모듈: 파일 시스템 고급 작업 배우기