본문 바로가기

Python

20210109_ Python 입문7, txt파일 읽기 쓰기, 에러 예외 처리

Python 입문 07


Python 파일 읽기와 쓰기

  Python에서 파일을 읽고, 쓰려면 기본적으로 open 함수와 with 문을 알아야 한다.

 

1. open 함수와 with

  • open함수를 통해 파일 객체를 생성해야 한다.
파일 객체 = open('./경로.파일이름', '파일 열기 모드')
  • 파일 열기 모드 : r(읽기모드) , w(쓰기모드), a(추가모드) <- read , write, append 의 앞글자

  • 그리고 파일객체.close()로 항상 파일 객체를 닫아주어야 한다. -> 안그러면 계속 파일이 열려있는 상태이고 다시 파일에 어떤 기능을 수행할때 부딪혀 에러가 난다.

  • 위 close 때문에 with을 통하면 with문이 끝나면 자동으로 닫힌다.

 

2. 파일 읽기

1) 접근법

f = open('./resource/review.txt', 'r') # 1. open함수를 사용하여 파일 객체를 지정해 본다.
print(type(f)      # 2. f 파일 객체가 어떤 타입인지 확인해 본다.
print(dir(f))      # 3. f 파일 객체가 어떤 함수(속성)를 가지고 있는지 본다.
                   # 4. read 함수가 있는 걸 확인했다.
content = f.read() # 5. read함수를 f에 사용하여 content에 반환해 본다.
print(content)     # 6. 값을 확인해 본다. 
f.close()          # 7. 사용한 파일을 닫아준다.

 

2) with,alias와 list 형 변환 활용 (iter 함수)

with open('./resource/review.txt','r') as f:
# 1. with문을 시작하고 open함수 사용하고 f로 alias 를 주었는데 위에서 한 파일객체 지정을 빠르게 준거라고 볼 수 있다.
    c = f.read() # 2. c에 파일 값을 반환해 본다.
    print(list(c)) # 3. list형으로 바꾸어 출력한다. list 사용시 for 문 사용 가능하다. 이때는 한 라인씩 리스트가 아니라 한 글자씩 리스트를 만듦
    print(iter(c)) # 3-1. iter 함수를 사용해 iterable 하게 만들어도 for 문이 가능하다. 이때는 1 line 씩 가져옴

 

3) 파일 읽기 for문 활용 (strip 함수)

with open('./resource/review.txt', 'r') as f: 
    for c in f: # 1. 파일 객체 f가 iterable 하기 때문에 바로 for 문에 사용
        print(c) # 2. 1 line(줄)씩 결과문이 나옴
# 3.  python은 print시 한줄이 끝나면 자동으로 엔터를 치는데 
# 기존에 파일을 작성하면서 친 엔터를 '/n'으로 받아 들여 먼저 엔터 치고 또 print시 엔터를 치게 되는 것  
        print(c.strip()) 
# 4. strip함수 사용하면 괄호안에 있는 문자(공백 포함)를 양쪽에 제거한다. 

 

4) read , readline , readlines

  • read 사용 (개행 포함)

   파일 전체의 내용을 하나의 문자열로 읽어온다.

with open('./resource/review.txt', 'r') as f: 
    content = f.read() # 1. 파일 전체를 읽어옴
    print(">", content) # 2. 전체를 읽어온걸 출력
    print(">", content) # 3. 전체를 읽어온걸 출력

    content = f.read() # 4. 근데 아직 파일이 꺼지지 않은 상태에서 이미 파일을 다 읽었는데 더읽을 수가 없음
    print(">", content) # 5. 내용 없음 출력

 

  • readline 사용 (개행 포함)

   한번에 하나의 라인을 읽어옴

with open('./resource/review.txt', 'r') as f: 
    line = f.readline() # 1. 한줄 읽고 현재 커서는 한줄 끝에 있음 
    while line:
        print(line, end='#### ') # 2. 개행 포함해서 가져오기 때문에 print시 개행을 '#### '으로 바꾸었음 그리고 1줄 출력
        line = f.readline() # 3. 다시 다음줄 읽어 오기

 

  • readlines 사용 (개행 포함)

   파일 전체를 한라인씩 읽어와서 리스트를 만들어줌

with open('./resource/review.txt', 'r' as f:
    content = f.readlines()
# 1. 개행 문자까지 포함한 한줄을 원소로 하는 파일 전체 list를 형성
    for c in content:
        print(c, end='') # 2. 원소 print시 개행을 '' 없애서 공백 줄 형태를 없앰

 

5) txt 파일 숫자 평균 구하기

score = [] # 1. 숫자 담을 score list 생성
with open('./resource/score.txt', 'r') as f:
    for c in f: # 2. f 파일에서 하나씩 가져와
        score.append(int(c))
    # 3. score list 에 가져온 c 를 숫자로 변환해서 넣어라
    print(score) # 4. score list 확인

print('Average : {0:3.2f}'.format(sum(score)/len(score)))
# 5. 출력해라 'Average : {0인덱스:3자리.소수점2자리 실수로}'.format(합/개수) # len 원소 숫자 세는 함수임

 

3. 파일 쓰기

  • 새로운 파일을 설정하고 open 하면 새롭게 만들어지고 내용이 들어가고, 기존 파일설정하고 내용 쓰면 덮어쓰기로 기존꺼는 삭제됨

 

  • 기본적으로 모드 w 변경, 함수만 write로 쓰면 똑같고 다만 내용 넣을 때 개행 \n을 내용 끝에 넣어줘야함 그래야 파일에서 줄바꿈이 됨

 

1) write , append

  • write
with open('./resource/text1.txt', 'w') as f: # 없는 파일도 경로 지정하고 write 모드로 변경
    f.write('Niceman!\n') # 개행 조심, 파일 생겼고 Niceman!이 쓰여져 있음

 

  • write 활용 (로또 번호 생성)
'로또 번호 생성'
from random import randint # 1. bulitins 패키지 중 하나 random에서 randint 함수를 가져온다
with open('./resource/text2.txt', 'w') as f:
    for cnt in range(6): 
    # 2. range 0~5까지 반복 
        f.write(str(randint(1, 46))) 
        # 3. f 파일에 쓴다. randint 랜덤한 정수(1에서, 45까지)를 str 문자로 변환해서
        f.write('\n') # 4. 개행 쓴다.

 

  • writelines를 통한 리스트 저장
with open('./resource/text3.txt', 'w') as f:
    list = ['kim\n','park\n','cho\n']
    f.writelines(list)

 

  • 쓰기 모드에서 결과값 파일에 저장(콘솔X)
with open('./resource/test4.txt', 'w') as f:
    print('test_message1!', file=f) # 결과값이 콜솔로 찍히지 않고 f파일로 들어가서 쓰여짐 
    print('test_message2!', file=f)

 

  • append(덮어쓰기X , 내용 추가)
with open('./resource/text1.txt', 'a') as f: # 해당 파일 경로 지정하고 append 모드로 변경
    f.write('Goodman!\n') # 아까 그 파일내 niceman! 바로 뒤에 붙여짐(\n 없으면) \n 이 있으면 줄바꿈으로 지정됨






Python 예외처리

  코드를 만들면서 에러가 발생하지 않을 순 없다. 그렇기 때문에 에러가 발생했을 때 어떻게 표시를 보이게 할 것인가 이다.

  보통 에러는 문법적 에러, 코드 실행(런타임)에러가 발생하는 데 주로 런타임 에러가 중요하다. 이렇게 에러들을 linter라고 코드 스타일, 문법체크 하게 도와주는 것이 있다.
python linter에서 내보내는 메세지를 알아보자

1. Error messages

1) SuntaxError : 잘못된 문법

  • 보통 ',: 누락 또는 존재하지 않는 문법을 사용한 경우 발생

2) NameError : 참조 변수 없음

  • 존재하지 않는 변수를 사용한 경우

3) IndexError : 인덱스 범위 오버

  • 존재하지 않는 인덱스를 사용하는 경우

4) KeyError : 키 에러

  • 존재하지 않는 키를 사용한 경우 (get메서드를 통해서 에러 발생을 막을수 있음 결과가 none이라고 발생)

5) AttributeError : 모듈, 클래스에 있는 잘못된 속성 사용시

  • 존재하지 않는 속성,함수, 클래스를 사용한 경우

6) ValueError : 참조 값이 없을 때

  • 존재하지 않는 값을 불러 올때

7) TypeError

  • 맞지 않는 타입 끼리 사용한 경우( + 사용시)

8) ZeroDivisionError

  • 0 나누기 에러

9) FileNotFoundError

  • 경로에 파일이 없는 경우

 

2. 예외 처리 구조

  • try : 에러가 발생할 가능성이 있는 코드
  • excet : 에러가 났을 때 하고자 하는 코드
  • else : 에러가 발생하지 않은 경우 코드
  • finally : 항상 실행 하고자 하는 코드

1) 어떤 에러가 날지 예상 가능한 경우

name = ['kim', 'lee', 'park']

try: # 1. 에러가 날 가능성이 있는 코드 작성(검사하고자 하는)
    z = 'kim' # z 가 kim 이면
    x = name.index(z) # x 에 kim 인덱스 리턴
    print('{} found it! {}in name'.format(z, x+1)) # kim foun it! 1 in name
except ValueError: # 2. z 가 kang 이면 ValueError 발생할 거니까 
    print('Not found it! - Occurred ValueError!') # 이때는 이렇게 실행
else:               # 3. try 문이 정상적으로 실행됬을때 나타남
    print('Ok! else!') 

 

2) 어떤 에러가 날지 모르는 경우

try:
    z = 'jin'
    x = name.index(z)
    print('{} found it! {}in name'.format(z, x+1)) 
except: # 그냥 except 처리 
    print('Not found it! - Occurred Error!')
else:
    print('Ok! else!')
finally: # 예외가 발생하든 아니든 무조건 출력
    print('finally ok!') #  보통 리소스 닫을때 f.close

 

3) 예외 처리 없이 그냥 접근하면 출력하는 코드

try:
    print('Try')
finally:
    print('ok finally!!')    # 코드 실행만 하면 출력 되므로 누군가가 접근하면 무조건 실행 되는 코드 임

 

4) 여러가지 에러에 대한 예외 처리 하여 필터링 식 코드

  • 순서 주의 해야함(Exception이 마지막에 와서 다 잡을 수 있도록 해야함)

  • except에 alias 사용도 가능

try:
    z = 'jin'
    x = name.index(z)
    print('{} found it! {}in name'.format(z, x+1)) 
except ValueError:                                 # 예외를 여러개 잡을 수 있음
    print('Not found it! - Occurred Error!')
except IndexError: #  as l 로 alias 잡고 print(l)로 설정하면 IndexError 그대로 표시함
    print('Not found it! - Occurred Error!')
except Exception:                                   # Exception 이 제일 위에 있으면 모두 잡기 때문에 뭔지 모르고 그후에 설정한 에러잡는 기능이 있으나 마나임
    print('Not found it! - Occurred Error!')        # 순서가 중요함 그래서 최종적으로 Exception을 준다.
else: 
    print('Ok! else!') 
finally: 
    print('finally ok!')

 

5) raise를 이용한 에러 직접 발생

try:
    a = '369'
    if a == 'kim':
        print("ok 허가!")
    else:
        raise ValueError # kim 씨가 아닌사람이 접근했을 때 ValueError를 일으켜서 알려주는 거지
except ValueError:
    print('문제발생!')
except Exception as f:
    print(f)
else:
    print('ok!')