Objectives
- 텍스트 파일 읽고 쓰기
- 이진 파일 읽고 쓰기
- 정규식 사용 방법
- CSV파일 읽고 쓰기
- 예외 처리 방법
10.2 파일의 기초
파일의 개념
🍋파일(file): 보조기억장치에서 문서, 소리, 그림, 동영상과 같은 자료를 모아놓은 것
파일은 보조기억장치 상에서 논리적인 정보 단위
파일 안에는 바이트들이 순차적으로 저장되어 있고 맨 끝에는 EOF(end-of-file)마커가 있음
모든 파일은 입출력 동작이 발생하는 위치를 나타내는 파일 포인터를 가지고 있음
파일을 처음으로 열면, 파일 포인터는 파일의 첫 번째 바이트를 가리킴
우리가 파일의 내용을 읽거나 쓰면 파일 포인터는 자동적으로 업데이트 됨
파일 열고 닫기
파일 연다-> 파일에서 데이터를 읽거나 쓴다->파일을 닫는다
Syntax: 함수 정의
#형식
파일 객체 = open(파일이름, 파일모드)
파일객체.close()
#예
infile=open("input."txt", "r")
...
infile.close()
파일 객체, 파일이름, 파일 여는 모드
open()의 첫 번째 매개 변수: 파일 이름
두 번째 매개 변수: 파일을 여는 모드
파일 모드
| 파일 모드 | 모드 이름 | 설명 |
| "r" | 읽기 모드(read mode) | 파일의 처음부터 읽다. |
| "w" | 쓰기 모드(write mode) | 파일의 처음부터 쓴다. 파일이 없으면 생성된다. 만약 파일이 존재하면 기존의 내용은 지워진다. |
| "a" | 추가 모드(append mode) | 파일의 끝에 쓴다. 파일이 없으면 생성된다. |
| "r+" | 읽기와 쓰기 모드 | 파일에 읽고 쓸 수 있는 모드이다. 모드를 변경하려면 seek()가 호출되어야 한다. |
파일에서 읽기
일반적으로 파일은 무척 클 수도 있기 때문에, 한 번에 다 읽기보다는 줄 단위로 끊어서 읽는 것이 보통
파일에서 한 줄을 읽으려면 파일 객체가 가지고 있는 readline() 메소드를 호출
파일을 열면 파일 포인터가 맨 첫 부분을 가리킴
readline()은 현재 위치에서 시작해서 현재 줄의 끝에 도달할 때까지 텍스트를 읽어서 반환
이후에 파일 포인터는 다음 줄로 이동
readline()은 줄의 끝을 나타내는 줄바꿈 문자까지 포함해서 반환함
infile=open("d:\\input.txt", "r")
line=infile.readline()
while line !="":
print(line)
line=infile.readline()
>>>홍길동
김철수
여기서 홍길동 다음에 빈 줄이 출력되는 것은 line 변수 안에 줄바꿈 문자인 "\n"이 저장되어 있기 때문
줄바꿈 문자를 삭제하려면 rstrip() 메소드 사용
rstrip(): 줄바꿈 문자와 같은 공백 문자들을 삭제하는 메소드
line=infile.readline().rstrip()
파일에 쓰기
outfile=open("input.txt", "w")
outfile.write("김영희\n")
콘솔에 출력할 때는 print() 함수가 자동으로 줄바꿈 문자를 붙이지만, 파일에 쓸 때는 줄바꿈 문자를 붙여서 보내주어야 함
print() 함수를 이용해서도 파일에 텍스트를 출력할 수 있음
file 매개 변수를 통해 파일 객체를 전달하면 됨
print("김영희", file=outfile)
변수의 값을 문자열 안에 포함시켜서 출력해도 됨
outfile.write(f"김영희 나이={age}\n")
outfile.write("김영희 나이=%s\n" %age)
파일 닫기
close() 사용
f=open("test.txt", "w") #파일 열기
f.write("홍길동\n")
f.close() #파일 닫기
안전하지 않은 방법
만약 파일 작업을 수행할 때 오류가 발생하면 파일을 닫지 않고 코드가 종료될 수 있음
try.. finally 블록 사용
try: #예외가 발생할 가능성이 있는 작업들을 여기에 둠
f=open("test.txt", "w")
f.write("홍길동") #여기서 여러 가지 작업 수행
finally:
f.close()
파일을 닫는 가장 좋은 방법: with 명령문 사용
with 명령문 내의 블록이 종료될 때 파일이 자동으로 닫힘
close()를 명시적으로 호출할 필요는 없음
close() 호출은 내부적으로 이루어짐
with open("test.txt", "w") as f:
f.write("김영희\n")
f.write("최자영\n")
#블록을 빠져나오면 자동으로 파일이 닫힘
10.3 다양한 텍스트 파일 입출력 방법
for-each 구문을 이용하는 방법
파일은 문자열들이 저장되어 있는 시퀀스(컨테이너) 객체로 볼 수 있음
for-each 구문 이용
파일의 모든 줄을 읽어서 콘솔에 출력하기
infile=open("scores.txt", "r")
for line in infile:
print(line)
각 반복에서 변수 line에 파일의 한 줄이 할당됨
for-each 구문을 사용하여 파일을 읽은 후에, 다시 읽으려면 파일을 닫았다가 열어야 함
줄바꿈 문자 제거
strip() 함수 호출
문자열의 첫 부분과 끝 부분에서 줄바꿈 문자같은 공백 문자 제거
문자 사이의 공백은 제거하지 않음
s=" Hello, World!\n"
s.strip()
>>>"Hello, World!"
rstrip(): 오른쪽 끝 원치 않는 문자 삭제
lstrip(): 왼쪽 끝 원치 않는 문자 삭제
단어로 분리하기
텍스트 파일에서 단어를 읽어야 하는 경우
ex) 속담이 저장된 파일에서 단어를 분리하여 리스트로 만들기
split()메소드 사용
split() 공백문자를 이용하여 문자열에서 단어들을 분리
infile=open("proverbs.txt", "r")
for line in infile:
line=line.rstrip() #오른쪽 공백 문자 없애기
word_list=line.split() #단어들로 분리
for word in word_list: 리스트에 들어 있는 단어들을 출력
print(word)
infile.close()
텍스트를 단어로 분리한 후에, 단어에 들어있는 모든 문장부호들을 제거하고 싶으면 rstrip(".,?!") 사용
word=word.rstrip(".,?!")
split() 호출할 때 분리자 지정 가능
ex) ,로 분리하는 경우
line="apple, grape, banana, pear"
word_list=line.split(",")
print(word_list)
>>>['apple', 'grape', 'banana', 'pear']
파일 전체 읽기
read()를 호출하면 파일의 모든 문자가 하나의 거대한 문자열로 반환됨
infile=open("input.txxt", "r")
s=infile.read()
print(s)
infile.close()
파일이 무척 크면 많은 양의 메모리를 필요로 하므로 좋은 방법은 아님
readlines() 메소드 사용
readlines()는 각 줄이 저장된 리스트를 반환
infile=open("input.txt", "r")
lines=infile.readlines()
for line in lines:
print(line)
infile.close()
문자 단위로 읽기
read()를 이용하여 원하는 개수만큼의 글자를 읽을 수도 있음
ex) 한 문자를 읽고 싶으면 read(1) 호출
infile=open("input.txt", "r")
ch=infile.read(1)
while ch!="":
print(ch)
ch=infile.read(1)
infile.close()
ex) read(1)을 이용하여 "mobydick.txt" 파일에 나오는 알파벳 문자들의 출현 횟수를 계산하는 코드 작성하기
대소문자 구별 안 하면 알파벳 문자 모두 26개
26개의 정수 저장 리스트 만들고 글자가 나오면 해당되는 숫자를 증가시키기
26개의 정수를 저장하는 리스트는 리스트 곱셈이나 리스트 함축으로 만들면 좋음
coutner=[0]*26
read(1) 호출해서 하나의 문자를 읽은 후에 문자의 번호 i를 알아내서 counter[i]를 하나 증가시키면 됨
i=ord(ch)-ord("A")
ord(ch): 문자 ch의 유니코드 값 반환
알파벳 문자는 "A"부터 시작되므로 ord(ch)에서 ord("A")를 빼면 현재 문자의 번호를 알 수 있음
문자 ord("A")는 65이고 만약 현재 문자가 "C"라면 ord("C")--ord("A")=67-65=2가 됨
i==ord(ch)-ord("A")
counter[i]+=1
파일의 모든 대문자는 소문자로 바꿔야 함
counter=[0]*26
infile=open("mobydick.txt", "r")
ch=infile.read(1)
while ch!="":
ch=ch.upper() #소문자->대문자
if ch>="A" and ch<="Z":
i=ord(ch)-ord("A")
counter[i]+=1
ch=infile.read(1)
print(counter)
문자 인코딩
컴퓨터에서 문자를 나타낼 때는 정수 형태의 문자 코드 사용
아스키 코드: 각 글자에 128개의 인코딩값 정의
유니코드 중에서 가장 많이 사용되는 인코딩: UTF-8
UTF-8: 각 문자를 1개에서 4개의 바이트로 인코딩
사용자가 UTF-8 기반의 파일을 열 때는 다음과 같이 인코딩을 지정해야 함
infile=open("input.txt", "r", encoding="utf=8")
10.4 디렉토리 작업
디렉토리에 있는 전체 파일을 찾아서 처리해야 하는 경우
디렉토리 얻는 함수
dir=os.getcwd()
data와 같은 서브 디렉토리에 저장되어 있다면
subdir="data"
os.chdir(subdir)
작업 디렉토리 안에 있는 파일들의 리스트 얻기
listdir() 함수 사용
for filename in os.listdir():
print(filename)
listdir() 함수: 작업 디렉토리 안에 있는 파일 뿐만 아니라 디렉토리 이름도 반환
파일만 처리하려면 isfile() 함수 사용
if os.path.isfile(filename):
print("파일입니다.")
endswidth(): 파일 확장자 검사
ex) 작업 디렉토리에서 확장자가 ".jpg"인 파일을 전부 찾아서 파일 이름을 출력하는 프로그램
import os
cwd=os.getcwd()
files=os.listdir()
for name in files:
if os.path.isfile(name):
if name.endswith(".jpg"):
print(name)
10.5 이진 파일과 임의 접근 파일
이진 파일
🍋이진 파일(binary file): 데이터가 직접 저장되어 있는 파일
이진수 형태로 그대로 파일에 기록 됨
이진 파일의 장점: 효율성
이진 파일의 단점: 인간이 파일의 내용을 확인하기가 힘듦, 이식성이 떨어짐. 모니터나 프린터로 출력 불가능.
이진 파일에서 데이터 읽으려면 다음과 같이 파일을 열어야 함
infile=open(filename, "rb")
입력 파일에서 8 바이트를 읽으려면 다음과 같은 문장 사용하기
bytesArray=infile.read(8)
bytesArray는 바이트형의 시퀀스로서 0부터 255까지의 값들의 모임
첫 번째 바이트를 꺼내려면 다음과 같은 문장 사용
byte1=bytesArray[0]
이진 파일에 바이트들을 저장하려면 다음과 같이 하기
outfile=open(filename, "wb")
bytesArray=bytes([255, 128, 0, 1])
outfile.write(bytesArray)
순차 접근과 임의 접근
🍋순차 접근(sequential access): 데이터를 파일의 처음부터 순차적으로 읽거나 기록하기
한번 읽은 데이터를 다시 읽으려면 현재의 파일을 닫고 파일을 다시 열어야 함
앞부분을 읽지 않고 중간이나 마지막으로 건너뛸 수도 없음
🍋임의 접근(random access): 파일의 어느 위치에서든지 읽기와 쓰기가 가능
임의 접근의 원리
모든 파일에는 파일 포인터라는 것이 존재
🍋파일 포인터(file pointer): 읽기와 쓰기 동작이 현재 어떤 위치에서 이루어지는 지를 나타냄
seck(): 위치 표시자 조작 함수
tell(): 현재 위치파악
infile.seek(position)
10.6 객체 출력
딕셔너리도 파일에 저장 가능
ex) 게임에서 플레이어의 현재 상태 파일에 저장
pickle 모듈의 dump()와 load() 메소드 사용
import pickle
객체를 pickle 모듈로 압축하려면 dump() 함수 사용
file=open("d:\\save.p", "w")
최종적으로 pickle 모듈의 dump() 호출
pickle.dump(gateOption, file)
피클 객체는 파이썬 객체를 직렬화하고 역질렬화하는 프로토콜 구현
피클 객체의 dump()를 호출하면 파이썬 객체가 바이트 스트림으로 변환되고,
load()를 호출하면 바이트 스트림이 객체로 변환됨
10.7 정규식
🍋정규식(regular expression): 특정한 규칙을 가지고 있는 문자열들을 메타 문자를 이용하여 표현하는 수식
메타문자(와일드카드)
| 식 | 기능 | 설명 |
| ^ | 시작 | 문자열의 시작을 표시 |
| $ | 끝 | 문자열의 끝을 표시 |
| . | 문자 | 한 개의 문자와 일치 |
| \d | 숫자 | 한 개의 숫자와 일치 |
| \w | 문자와 숫자 | 한 개의 문자나 숫자와 일치 |
| \s | 공백문자 | 공백, 탭, 줄바꿈, 캐리지리턴 문자와 일치 |
| \S | 공백문자제외 | 공백 문자를 제외한 모든 문자 |
| * | 반복 | 0번 이상 반복 |
| + | 반복 | 1번 이상 반복 |
| [abc] | 문자 범위 | [abc]는 a 또는 b 또는 c를 나타냄 |
| [^abc] | 문자 범위 | [^abc]는 a,b,c가 아닌 어떤 문자 |
메타 문자 중에서 가장 중요한 문자: 점(.)과 별표(*)
-점: 어떤 문자가 와도 상관 없다는 의미
-별표: 몇 번 반복되어도 상관없다는 것을 의미
^X-Men.*
위의 정규식은 문자열은 X-Men으로 시작하여야 되고 그 이후에는 어떤 문자가 반복되더라도 좋다는 것을 나타냄
^: 문자열의 시작
.: 어떤 문자
*: 몇 번이고 올 수 있음
파이썬에서 정규식을 사용하려면 re모듈 포함시켜야 함
import re
re.search(): 정규식에 매치되는 문자열 찾기 가능
re.findall(): 정규식을 만족하는 모든 문자열들 추출 가능
ex) 미국 헌법에서 숫자로 싲가되는 줄만을 출력하는 프로그램
import re
f=open('d:/uscons.txt')
for line in f:
line=line.rstrip()
if re.search('^[0-9]+', line):
print(line)
멀티라인 문자열은 """..."""으로 나타내기
10.8 예외 처리
🍋역추적(traceback) 메시지: 오류 메시지
예외 처리
🍋예외(exception): 파이썬에서 실행 도중에 발생하는 오류
오류가 발생했을 때 오류를 사용자에게 알려주고 모든 데이터를 저장한 후에 사용자가 우아하게(gradeflly)프로그램을 종료할 수 있도록 하는 것이 바람직
try/execpt 블록에서의 실행 흐름
예외 발생하는 경우에 except 실행
다중 예외 처리 구조
하나의try 문자은 여러 개의 except 문장 가질 수 있음
하나의 문장에서 많은 예외가 발생할 수 있는 경우에 유용
예외가 기술되지 않은 except 블록
except 블록을 만들 때 자세한 예외의 내용을 적지 않으면 어떠한 예외라도 처리할 수 있는 except 블록이 됨
하지만 모든 예외를 잡기 때문에 문제의 근본을 알 수 없다는 문제가 생김
try: #예외가 발생할 수 있는 문장
.........
except: #어떠한 예외라도 발생하면 여기서 처리
.........
else: #예외가 없다면 이 블록이 실행됨
여러 개의 예외를 가지는 except 블록
try: #예외가 발생할 수 있는 문장
.........
except(exception1[, exception2[, ...exceptionN]]]): #어떠한 예외라도 발생하면 여기서 처리
.........
else: #예외가 없다면 이 블록이 실행됨
try-finally 블록
finally 블록은 오류가 발생한 경우나 아니면 발생하지 않은 경우에도 항상 실행되어야 하는 문장을 두는 블록
finally 블록은 항상 실행됨
try: #예외가 발생할 수 있는 문장
...........
#여기 문장은 예외가 발생하면 실행되지않을 수 있다.
finally: #항상 실행됨
............
파일을 다루는 경우에는 예외 여부와 상관없이 항상 파일을 닫아야 함
이러한 경우에 finally 블록이 사용됨
try:
f=open("test.txt", "w")
f.write("테스트 데이터를 파일에 씁니다!")
except IOError:
print("Error: 파일을 찾을 수 없거나 데이터를 쓸 수 없습니다.")
finally:
f.close()
예외 발생하기
raise 키워드: 예외 생성
파이썬에서는 오류가 감지되면 raise문을 사용하여 예외 생성
raise exception
'프로그래밍 > Python' 카테고리의 다른 글
| 📔파워 유저를 위한 파이썬 Express: 12. 상속 (0) | 2025.05.09 |
|---|---|
| 📔파워 유저를 위한 파이썬 Express 11. 내장함수, 람다식, 제너레이터, 모듈 (0) | 2023.07.13 |
| 📔파워 유저를 위한 파이썬 Express 09. GUI 프로그래밍 - Programming 문제 풀이 (0) | 2023.06.05 |
| 📔파워 유저를 위한 파이썬 Express09. GUI 프로그래밍 (0) | 2023.06.02 |
| 📔파워 유저를 위한 파이썬 Express08. 객체와 클래스 Programming 문제풀이 (1) | 2023.05.29 |