본문 바로가기

카테고리 없음

[데이터과학을위한파이썬프로그래밍] 12 예외처리, 파일읽고쓰기

01 예외처리

[1] 예외의 개념과 사례

예외 : 프로그램을 개발하며 예상하지 못한 상황이 발생하는 것

  1. 예측가능한 예외 - if
  2. 예측 불가능한 예외 - try-except문

예외의 종류

: IndexError (리스트인덱스범위넘어갈때)

NameError (존재하지 않는 호출할 때)

ZeroDivisionError (0으로 숫자를 나눌 때)

ValueError (변환할 수 없는 문자나 숫자를 변환할 때)

FileNotFoundError (존재하지 않는 파일을 호출할 때)

 

3.1 try-except문

try: 예외 발생 가능 코드 except 예외 타입: 예외 발생 시 실행되는 코드

try:
    print(10/0)
except:
    print("Not divided by 0")

#except문장 실행됨 Not divided by 0
#응용
for i in range(10):           #0,1,2,3,4,5,6,7,8,9
    try:
        result=10/i
    except ZeroDivisionError:
        print("Not divided by 0")

'''
Not divided by 0 - 10/0
'''

 

3.2 try-except-else문

try: 예외 발생 가능 코드 except 예외 타입: 예외 발생 시 실행되는 코드 else: 예외가 발생하지 않을 때 실행되는 코드

for i in range(10):           #0,1,2,3,4,5,6,7,8,9
    try:
        result=10/i
    except ZeroDivisionError:
        print("Not divided by 0")
    else:
        print(10/i)
'''
Not divided by 0 - 10/0
10.0 - 10/1
5.0 -10/2
3.3333333333333335
2.5
2.0
1.6666666666666667
1.4285714285714286
1.25
1.1111111111111112 - 10/9
'''

 

3.3 try-except-finally문

try: 예외 발생 가능 코드 except 예외 타입: 예외 발생 시 실행되는 코드 else: 예외가 발생하지 않을 때 실행되는 코드

try:
    for i in range(1,10):
        result=10//i
        print(result)
except ZeroDivisionError:
    print("Not divided by 0")
finally:
    print('종료되었다.')

#finally까지가 시험범위
'''
10
5
3
2
2
1
1
1
1
종료되었다.'''

 

 

 

 

 

02 파일 다루기

[파일 읽기]

파이썬에서는 텍스트 파일을 다루기 위해 open() 함수를 사용한다. 일반적으로 open() 함 수와 파일명, 파일 열기 모드를 적용하면, 이에 따라 파일을 열고 다룰 수 있다.

f = open("파일명", "파일 열기 모드") f.close()

 

<파일 읽기 실행하기>

#fileopen.py
1 f = open("dream.txt", "r")
2 contents = f.read()
3 print(contents)
4 f.close()

—-
I have a dream a song to sing
to help me cope with anything
if you see the wonder of a fairy tale

1행에서 open() 함수 다음에 파일명과 을 사용하면 파일의 정보를 변수에 저장할 수 있다. 이를 일반적으로 파일 객체라고 한다.

2행에서 변수에서 read() 함수를 실행하면 해당 텍스트 파일의 텍스트를 contents 변수에 문자열로 저장한다.

3행에서는 'dream.txt' 파일을 불러와 화면에 출력한다.

4행에서는 최종으로 close() 함수를 사용하여 파일을 종료한다.

때때로 텍스트 파일을 수정할 때 이미 수정하고 있는 파일을 다른 프로그램이 함께 호출하면 에러가 발생하는데, 이렇게 하나의 파이썬 프로그램이 하나의 파일을 쓰고 있을 때 사용을 완료하면 반드시 해당 파일을 종료해야 한다.

<with문과 함께 사용하기>

#fileopen2.py
1 with open("dream.txt","r") as my_file:
2     contents = my_file.read()
3     print(type(contents), contents)

—-
<class 'str'> I have a dream a song to sing
to help me cope with anything
if you see the wonder of a fairy tale

with문과 함께 open()함수를 사용할 수 있다. with문은 들여쓰기를 사용해 들여쓰기가 있는 코드에서는 open() 함수가 유지되고, 들여쓰기가 종료되면 open() 함수도 끝나는 방식이다.

[코드 open()]과의 차이는 close() 함수를 명시적으로 쓰지 않아도 파일의 사용을 종료할 수 있다는 점이다.

해당 파일 객체는 as문을 사용하여 변수명에 할당한다

 

<실행할 때마다 한 줄씩 읽어오기> readline()

#fileopen4.py
with open(dir, "r") as my_file:  # "dir"에 지정된 파일을 읽기 모드로 엽니다.
    i = 0                        # i 변수를 초기화합니다.
    
    while 1:                       # 무한 루프를 시작합니다.
        line = my_file.readline()  # 파일에서 한 줄씩 읽어옵니다.
        
        if not line:               # 만약 더 이상 읽을 줄이 없다면 (line이 비어 있다면)
            break                  # 루프를 종료합니다.
        
        print(str(i) + " : " + line.replace("\n", ""))  
        # 현재 줄 번호와 줄 내용을 출력합니다. 개행 문자(\n)는 제거("")합니다.
        
        i = i + 1                  # 줄 번호를 1 증가시킵니다

---
0 : 홍길동 010-1234-5678
1 : 홍길순 010-1212-3535
2 : 박길동 010-1212-3434

#책
0 : I have a dream a song to sing
1 : to help me cope with anything
2 : if you see the wonder of a fairy tale

while 1로 코드가 항상 작동하게 만든 다음, 4행의 line = my_file.readline)으로 한 줄씩 파일을 읽어 온다.

만약 읽어 온 줄에 내용이 없다면 5행의 if not line: break 코드에 의해 반복문이 종료되어 파일을 그만 읽게 된다. 하지만 파일에 남은 내용이 있다면 while이 계속 실행되면서 모든 코드를 다 읽어 오게 된다. 일반적으로 파일의 내용을 찾다가 중간에 멈춰야 할 필요가 있는 대용량 데이터는 위와 같은 코드를 많이 사용한다.

 

< 한 줄씩 읽어 리스트형으로 반환하기 > readlines()

#readlines() - 리스트 자료형 반환
# 파일 경로 지정
dir = "/content/drive/MyDrive/고파썬/file2/phones.txt"

# 파일을 읽기 모드로 열고 with 구문을 사용하여 자동으로 파일을 닫음
with open(dir, "r") as f:
    # 파일의 모든 내용을 읽어와 각 줄을 리스트로 저장
    contents = f.readlines()
    
    # 리스트의 데이터 타입 출력 (이 경우 리스트임)
    print(type(contents))
    
    # 파일의 내용 전체를 리스트 형태로 출력
    print(contents)

# 파일이 자동으로 닫힘
---
<class 'list'>
['홍길동 010-1234-5678\n', '홍길순 010-1212-3535\n', '박길동 010-1212-3434']

#책
['I have a dream a song to sing \n', 'to help me cope with anything\n', 
'if you see the wonder of a fairy tale\n']

*readline & readlines()

#+chatgpt - readline()으로 가져오기!

dir = 'C:\PYTHON\phones.txt'

#while문 
with open(dir, "r", encoding="utf-8") as f:
    while True:  # 무한 루프 시작
        line = f.readline()  # 파일에서 한 줄을 읽어옵니다.
        if not line:  # 더 이상 읽을 줄이 없으면 반복문을 종료합니다.
            break
        print(line.strip())  # 줄바꿈 문자를 제거하고 해당 줄을 출력합니다.
        
        
#for문
with open(dir, "r", encoding="utf-8") as file:
    for line in file:  # 파일 객체를 직접 반복하여 각 줄을 읽습니다.
        print(line.strip())  # 각 줄에서 줄바꿈 문자를 제거하고 출력합니다.
        
---
홍길동 010-1234-5678
홍길순 010-1212-3535
박길동 010-1212-3434
#readlines() - 리스트 자료형 반환
dir = "/content/drive/MyDrive/고파썬/file2/phones.txt" # 파일 경로를 변수 dir에 저장합니다.
with open(dir, "r", encoding="utf-8") as f:                             # 파일을 읽기 모드로 엽니다.
    contents = f.readlines()                          # 파일의 모든 내용을 읽어 리스트로 반환합니다.
    print(type(contents))                             # contents 변수의 자료형을 출력합니다.
    print(contents)                                   # contents 변수를 출력합니다.
f.close()                                             # 파일을 닫습니다.

---
<class 'list'>
['홍길동 010-1234-5678\\n', '홍길순 010-1212-3535\\n', '박길동 010-1212-3434']
  • readlines()와 readline()의 차이readlines() 함수는 파일의 각 줄을 리스트 요소로 반환합니다. 각 줄의 끝에는 개행 문자(\\n)가 포함되어 있습니다.
  • 반면에 readline() 함수는 파일에서 한 줄씩 읽습니다. 매번 호출될 때마다 다음 줄을 읽고 문자열로 반환합니다.
  • readlines() 함수는 파일의 모든 내용을 한 번에 읽고, 각 줄을 요소로 갖는 리스트를 반환

<파일 안 글자의 통계 정보 출력하기>

때로는 파일 안 텍스트의 통계 정보를 읽어 와야 할 때가 있다.

이를 위해 많이 사용하는 방법은 이미 배운 split() 함수와 len() 함수를 함께 사용하는 것이다.

아래는 파일 안의 모든 텍스트를 읽어 온 후 차례대로 글자 수, 단어 수, 줄 수를 출력하는 프로그램이다.

#파일에 저장된 글자의 통계 정보 출력하기
dir = 'C:\PYTHON\hbd.txt'
'''
Happy birthday to you
Happy birthday to you 
Happy birthday, dear k;
Happy birthday to you.
'''

#파일에 저장된 글자의 통계 정보 출력하기
with open(dir, "r") as my_file:
    contents = my_file.read()
    word_list = contents.split(" ")  ##빈칸 기준으로 단어를 분리 리스트
    line_list = contents.split("\n") ## 한 줄씩 분리하여 리스트

print("총 글자:",len(contents))  # 읽어온 내용의 글자 수를 출력합니다.
print("총 단어:",len(word_list)) # 단어 리스트의 길이를 출력합니다.
print("총 줄:",len(line_list))   # 줄 리스트의 길이를 출력합니다.

---
총 글자: 91
총 단어: 14
총 줄: 4

+단어별빈도수세기

#collections 모듈 사용
from collections import Counter  # collections 모듈로부터 Counter 클래스 import

dir = 'C:\\\\PYTHON\\\\hbd.txt'

# 파일을 읽기 모드로 열고 with 구문을 사용하여 자동으로 파일을 닫음
with open(dir, "r") as my_file:
    contents = my_file.read()  # 파일의 내용을 모두 읽어옴
    words = contents.split()   # 읽어온 내용을 공백을 기준으로 단어 리스트 생성

# Counter 클래스를 사용하여 각 단어의 빈도수를 세어서 딕셔너리 형태로 저장
word_frequency = Counter(words)

# 단어별 빈도수를 출력
print("단어별 빈도수:", word_frequency)  # Counter 클래스를 사용하여 얻은 단어별 빈도수를 출력
#for문 사용
dir = 'C:\\\\PYTHON\\\\hbd.txt'

# 파일을 읽기 모드로 열고 with 구문을 사용하여 자동으로 파일을 닫음
with open(dir, "r") as my_file:
    contents = my_file.read()  # 파일의 내용을 모두 읽어옴
    words = contents.split()   # 읽어온 내용을 공백을 기준으로 단어 리스트 생성

# 각 단어의 빈도수를 셈
word_count = {}                # 빈 딕셔너리를 생성하여 단어의 빈도수를 저장할 준비
for word in words:             # 단어 리스트를 순회하면서 각 단어의 빈도수를 세어봄
    if word in word_count: # 해당 단어가 이미 딕셔너리에 존재하면
        word_count[word] += 1  # 해당 단어의 빈도수를 1 증가시킴
    else:                  # 해당 단어가 딕셔너리에 존재하지 않으면
        word_count[word] = 1   # 새로운 단어로 추가하고 빈도수를 1로 초기화함

# 단어별 빈도수를 출력
print("단어별 빈도수:", word_count)  # 딕셔너리에 저장된 단어별 빈도수를 출력

 

[파일 쓰기]

파일을 쓰기 위해서는 파일 열기 모드를 'w'로 설정하는 것과 함께 인코딩 encoding이라는 개념을 알아야 한다. 텍스트 파일을 저장하기 위해서는 저장할 때 사용하는 표준을 지정해야 하는데, 이것을 인코딩이라고 한다. 인코딩의 옵션으로 인코딩 표준을 지정한다. 일반적으로 인코딩은 utf8을 많이 사용하며, 파일을 윈도에서만 사용한다면 cp949도 사용한다. 인코딩은 운영체제나 파일의 사용 환경에 따라 다르게 설정해야 한다.

아래 코드를 실행하면 'count~.txt'라는 파일을 생성한 후 1부터 10까지의 숫자가 데이터에 할당되면서 '1번째 줄이다.'라는 텍스트를 '10번째 줄이다.'까지 차례대로 f.write(data)코드로 count~.txt 파일에 기록된다. 모든 내용을 기록한 후에 f.close() 코드로 해당 파일은 종료된다.

#파일쓰기모드
dir2 = "/content/drive/MyDrive/고파썬/file2/count.txt"
f = open(dir2, 'w', encoding="utf8")

for i in range(1,11):
    data = "%d번째 줄이다. \\n"% i
    f.write(data)
f.close()
---
1번째 줄이다. 2번째 줄이다. 3번째 줄이다. 4번째 줄이다. 5번째 줄이다. 6번째 줄이다. 7번째 줄이다. 8번째 줄이다. 9번째 줄이다. 10번째 줄이다.

 

  • 연습문제
    #04 다음과 같이 각각의 예외 처리에 적합한 
    #   내장 예외(bult-in exception)를 순서대로 실행한 결과값이 바르게 짝지어진 것은?
    
    # (가) - IndexError 예외 발생 상황
    alist = ["a", "1", "c"]
    blist = ["b", "2", "d"]
    for a, b in enumerate(zip(alist, blist)):
        try:
            print(b[a])             # 리스트 b에서 a번째 요소를 출력합니다.
        except IndexError:          # IndexError가 발생하면 처리합니다.
            print("Index Error 발생")  
    
    # (나) - ValueError 예외 발생 상황
    alist = ["a", "1", "c"]
    blist = ["b", "2", "d"]
    for a, b in enumerate(zip(alist, blist)):
        try:
            result = a / int(b[0])  # a를 b의 첫 번째 요소로 나눕니다.
            print(result)
        except ValueError:          # ValueError가 발생하면 처리합니다.
            print("Value Error 발생")
import random

# 1부터 10 사이의 랜덤한 정수를 answer 변수에 저장
answer = random.randint(1, 10)

# guess_number 함수 정의, answer를 매개변수로 받음
def guess_number(answer):
    try:
        # 사용자로부터 숫자를 입력받음
        guess = int(input("숫자를 넣어 주세요: "))
        
        # 입력한 숫자와 정답을 비교하여 결과 출력
        if answer == guess:
            print("정답!")
        else:
            print("틀렸습니다.")
    except ValueError:
        # 입력값이 숫자로 변환할 수 없을 경우 예외 처리
        print("숫자가 아닙니다.")

# guess_number 함수 호출하여 실행
guess_number(answer)

---
숫자를 넣어 주세요: 헬로
숫자가 아닙니다

 

#10 다음과 같이 코드를 작성했을 때, 실행 결과로 알맞은 것은?
for i in range(3):               #for 루프를 사용, 0~2까지의 값을 반복
    try:
        print(i, 3 // i)         #현재의 i 값과 3을 i로 나눈 몫을 출력
    except ZeroDivisionError:    #i가 0일 때, ZeroDivisionError예외 발생
        print("Not divided by 0")

---
Not divided by 0
1 3
2 1