혼공파 5주차

JIN·2023년 8월 10일
0

혼공단 10기

목록 보기
5/7
post-thumbnail

🔎 구문 오류와 예외


오류의 종류

  1. 프로그램 실행 전에 발생하는 오류 : 구문 오류(Syntax Error)
  2. 프로그램 실행 중에 발생하는 오류 : 예외(exception), 런타임 오류(runtime error)

구문 오류(Syntax Error)

  • 괄호 개수, 들여쓰기 문제 등으로 프로그램이 실행되기도 전에 발생하는 오류
  • 구문에 문제가 있어 프로그램이 실행조차 되지 않는 오류
  • 코드를 제대로 작성하면 프로그램이 정상적으로 작동함

예외(exception) 또는 런타임 오류(Runtime Error)

  • 프로그램이 일단 실행한 다음 실행 중에 발생하는 오류
  • 코드를 제대로 작성하면 프로그램이 정상적으로 작동함

예외 처리(exception handling)

  • 예외를 해결하는 모든 것
  • 예외가 발생하지 않게 미리 예외가 발생할 수 있는 부분에 안전 장치를 설치하는 것
  • 예외처리는 조건문을 사용하거나 try구문을 사용하면 됨

기본 예외 처리

  • 조건문을 사용해서 예외를 처리하는 방법
# 숫자 입력
number_input_a = int(input("정수 입력> "))

# 출력
print("원의 반지름:", number_input_a)
print("원의 둘레:", 2 * 3.14 * number_input_a)
print("원의 넓이:", 3.14 * number_input_a * number_input_a)
  • 위의 코드를 실행하면 정수이면 정상작동을 할 것이고, 정수가 아니면 정상작동하지 않을 것임
  • 이런 예외를 해결하기 위하여 아래와 같이 isdigit()함수를 이용하여 정수로만 구성되어 있는지 확인하고 코드를 실행할 수 있도록 변경해줌
# 숫자 입력
user_input_a = input("정수 입력> ")

# 사용자 입력이 숫자로만 구성되어 있을 때
if user_input_a.isdigit():
	# 숫자로 변환
    number_input_a = int(user_input_a)
    # 출력
    print("원의 반지름:", number_input_a)
    print("원의 둘레:", 2 * 3.14 * number_input_a)
    print("원의 넓이:", 3.14 * number_input_a * number_input_a)
else:
	print("정수를 입력하지 않았습니다.")

try except 구문

  • 예외 처리에 특화된 구문
  • 예외가 발생할 가능성이 있는 코드는 모두 try구문에 넣음
  • 예외가 발생했을 때 실행할 코드는 모두 except구문에 넣음

    try:
    . . . . 예외가 발생할 가능성이 있는 코드
    except:
    . . . . 예외가 발생했을 때 실행할 코드

오류가 났던 위의 코드를 조건문이 아닌 try except구문을 사용하면 아래처럼 작성할 수 있음

try:
	# 숫자로 변환
    number_input_a = int(input("정수 입력> "))     # 예외가 발생할 가능성이 있는 구문
    # 출력
    print("원의 반지름:", number_input_a)
    print("원의 둘레:", 2 * 3.14 * number_input_a)
    print("원의 넓이:", 3.14 * number_input_a * number_input_a)
except:
	print("무언가 잘못되었습니다.")     # 예외가 발생했을 때 실행할 구문

try except 구문과 pass키워드 조합

  • 이유는 정확하게 모르지만 어디에 오류가 났는지 정확하게 알아야 하는 상황에 사용함
  • 예외가 발생하면 일단 처리해야 하지만, 해당 코드가 중요한 부분이 아니라면 일단 프로그램이 강제 종료되는 것부터 막자는 목적으로 except 구문에 아무것도 넣지 않고 try구문을 사용하게 됨
  • 구문 내부에 아무 것도 넣지 않으면 구문 오류가 발생하므로 pass키워드를 넣어서 사용함

    try:
    . . . . 예외가 발생할 가능성이 있는 코드
    except:
    . . . . pass

# 변수 선언
list_input_a = ["52", "273", "32", "스파이", "103"]

# 반복 적용
list_number = []
for item in list_input_a:
	# 숫자로 변환해서 리스트에 추가
    try:
    	float(item)
        list_number.append(item)
    except:
    	pass
        
#출력
print("{} 내부에 있는 숫자는".format(list_input_a))
print("{}입니다.".format(list_number))

try except else 구문

  • try except 구문 뒤에 else 구문을 붙여서 사용하면 '예외가 발새하지 않았을 때 실행할 코드'를 지정 가능함
  • 예외가 발생할 가능성이 있는 코드만 try 구문 내부에 넣고 나머지를 모두 else 구문으로 빼는 경우가 많음

    try:
    . . . . 예외가 발생할 가능성이 있는 코드
    except:
    . . . . 예외가 발생했을 때 실행할 코드
    else:
    . . . . 예외가 발생하지 않았을 때 실행할 코드

# try except else 구문으로 예외 처리
try:
	# 숫자로 변환
    number_input_a = int(input("정수 입력> "))
except:
	print("정수를 입력하지 않았습니다.")
else:
	# 출력
    print("원의 반지름:", number_input_a)
    print("원의 둘레:", 2 * 3.14 * number_input_a)
    print("원의 넓이:", 3.14 * number_input_a * number_input_a)

finally 구문

  • 예외 처리 구문에서 가장 마지막에 사용할 수 있는 구문
  • 예외가 발생하든 발생하지 않든 무조건 실행할 때 사용하는 코드
  • 어떤 조건에 무조건 사용해야 하는 것이 아니라, finally 키워드를 사용하면 코드가 깔끔해 질 것 같다고 생각되는 경우에 사용함

    try:
    . . . . 예외가 발생할 가능성이 있는 코드
    except:
    . . . . 예외가 발생했을 때 실행할 코드
    elxe:
    . . . . 예외가 발생하지 않았을 때 실행할 코드
    finally:
    . . . . 무조건 실행할 코드

# try except 구문으로 예외를 처리함
try:
	# 숫자로 변환함
    number_input_a = int(input("정수 입력> "))
    # 출력
    print("원의 반지름:", number_input_a)
    print("원의 둘레:", 2 *  .14 * number_input_a)
    print("원의 넓이:", 3.14 * number_input_a * number_input_a)
    
except:
	print("정수를 입력하지 않았습니다.")
else:
	print("예외가 발생하지 않았습니다.")
finally:
print("일단 프로그램이 어떻게든 끝났습니다.")

try, except, finally 구문의 조합

  • try 구문은 단독으로 사용할 수 없으며, 반드시 except 구문 또는 finally 구문과 함께 사용해야 함
  • else 구문은 반드시 except 구문 뒤에 사용해야 함
  • 형식을 맞추지 않으면 구문 오류(Syntax Error)가 발생함

    try + except 구문 조합
    try + except + else 구문 조합
    try + except + finally 구문 조합
    try + except + else + finally 구문 조합
    try + finally 구문 조합




예외 고급


예외 객체(exception object)

  • 예외가 발생했을 때 예외에 관련된 정보가 저장되는 객체

    try:
    . . . . 예외가 발생할 가능성이 있는 구문
    except 예외의 종류 as 예외 객체를 활용할 변수 이름:
    . . . . 예외가 발생했을 때 실행할 구문

# try except 구문으로 예외 처리
try:
    # 숫자로 변환
    number_input_a = int(input("정수 입력> "))
    # 출력
    print("원의 반지름:", number_input_a)
    print("원의 둘레:", 2, * 3.14 * number_input_a)
    print("원의 넓이:", 3.14 * number_input_a * number_input_a)
except Exception as exception:
    # 예외 객체 출력
    print("type(exception):", type(exception))
    print("exception:", exception)

# 실행 결과
----------
type(exception): <class 'ValueError'>
exception: invalid literal for int() with base 10: 'yes!!'

예외 구분하기

  • 예외 객체를 사용하면 except 구문을 if 조건문처럼 사용해서 예외 구분 가능

    try:
    . . . . 예외가 발생할 가능성이 있는 구문
    except 예외의 종류 A:
    . . . . 예외 A가 발생햇을 때 실행할 구문
    except 예외의 종류 B:
    . . . . 예외 B가 발생했을 때 실행할 구문
    except 예외의 종류 C:
    . . . . 예외 C가 발생했을 때 실행할 구문

# 변수 선언
list_number = [52, 273, 32, 72, 100]

# try except 구문으로 예외 처리
try:
    # 숫자 입력
    number_input = int(input("정수 입력> "))
    # 리스트 요소 출력
    print("{}번째 요소: {}".format(number_input, list_number[number_input]))
except ValueError:
    #ValueError가 발생하는 경우
    print("정수를 입력해 주세요!")
except IndexError:
    # IndexError가 발생하는 경우
    print("리스트의 인덱스를 벗어났어요!")
    
# 실행 결과
----------
정수를 입력해 주세요!

예외 구분 구문과 예외 객체

  • 예외를 구분할 때 각각의 except 구문 뒤에 예외 객체를 붙여 활용 가능함
  • as키워드 사용하면 됨
# 변수 선언
list_number = [52, 273, 32, 72, 100]

# try except 구문으로 예외 처리
try:
    # 숫자 입력
    number_input = int(input("정수 입력> "))
    # 리스트 요소 출력
    print("{}번째 요소: {}".format(number_input, list_number[number_input]))
except ValueError as exception:
    #ValueError가 발생하는 경우
    print("정수를 입력해 주세요!")
    print("exception:", exception)
except IndexError as exception:
    # IndexError가 발생하는 경우
    print("리스트의 인덱스를 벗어났어요!")
    print("exception:", exception)
    
# 실행 결과
----------
리스트의 인덱스를 벗어났어요!
exception: list index out of range

모든 예외 잡기

  • 예외가 발생하여 프로그램이 종료되는 경우에 Exception을 넣어서 프로그램 실행을 중단시키지 않고 계속 실행함
# 변수 선언
list_number = [52, 273, 32, 72, 100]

# try except 구문으로 예외 처리
try:
    # 숫자 입력
    number_input = int(input("정수 입력> "))
    # 리스트 요소 출력
    print("{}번째 요소: {}".format(number_input, list_number[number_input]))
    예외.발생해주세요()          # 이 부분에서 잡지 않은 예외 발생하도록 함
except ValueError as exception:
    #ValueError가 발생하는 경우
    print("정수를 입력해 주세요!")
    print("exception:", exception)
except IndexError as exception:
    # IndexError가 발생하는 경우
    print("리스트의 인덱스를 벗어났어요!")
    print("exception:", exception)
except Exception as exception:
# 이외의 예외가 발생한 경우
    print("미리 파악하지 못한 예외가 발생했습니다.")
    print(type(exception), exception)
    
# 실행 결과
----------
1번째 요소: 273
미리 파악하지 못한 예외가 발생했습니다.
<class 'NameError'> name '예외' is not defined

raise 구문

  • 아직 구현되지 않은 부분에 일부러 예외를 발생시켜 프로그램을 죽게 만즐어 잊어버리지 않도록 하는 것

    raise 예외 객체

# 입력 받음
number = input("정수 입력> ")
number = int(number)
# 조건문 사용
if number > 0:
    # 양수일 때: 아직 미구현 상태
    raise NotImplementedError
else:
    # 음수일 때: 아직 미구현 상태
    raise NotImplementedError



🔎 표준 모듈


모듈(module)

  • 코드를 분리하고 공유할 수도록 만들어 주는 문법
    표준 모듈 : 파이썬에 기본적으로 내장되어 있는 모듈
    외부 모듈 : 다른 사람이 만들어서 공개한 모듈

    import 모듈 이름


모듈 사용의 기본: math 모듈

  • 수학과 관련된 기능을 가지고 있음

    import math


모듈 문서

변수 또는 함수설명
sin(x)사인값을 구함
cos(x)코사인값을 구함
tan(x)탄젠트값을 구함
log(x[, base]로그 값을 구함
ceil(x)올림함
floor(x)내림함

from 구문

  • 가져오고 싶은 변수, 함수를 한 번에 가져오고 싶을 때 사용함

    from 모듈 이름 import 가져오고 싶은 변수 또는 함수


as 구문

  • 모듈을 가져올 때 이름 충돌이 발생하거나 모듈의 이름을 짧게 줄여 사용하고 싶을 때 사용함

    import 모듈 as 사용하고 싶은 식별자


random 모듈

  • 랜덤한 값을 생성할 때 사용함
  • from 구문 또는 as 구문과도 조합해서 사용 가능함
  • random모듈은 from 구문을 활용해서 import 하는 것이 일반적

    import random

import random
print("# random 모듈")

# random(): 0.0 <= x < 1.0사이의 float를 리턴함
print("- uniform(10, 20):", random.uniform(10, 20))

# randrange(): 지정한 범위의 int를 리턴
# - randrange(max): 0부터 max 사이의 값 리턴
# - randrange(min, max): min부터 max 사이의 값을 리턴
print("-randrange(10):", random.randrange(10))

# choice(list): 리스트 내부에 있는 요소를 랜덤하게 선택
print("- choice([1, 2, 3, 4, 5]):", random.choice([1, 2, 3, 4, 5]))

# shuffle(list): 리스트의 요소들을 랜덤하게 섞음
print("- shuffle([1, 2, 3, 4, 5]):", random.shuffle([1, 2, 3, 4, 5]))

# sample(list, k=<숫자>): 리스트의 요소 중에 k개를 뽑음
print("- sample([1, 2, 3, 4, 5]):", random.sample([1, 2, 3, 4, 5], k=2))

# 실행 결과
----------
# random 모듈
- uniform(10, 20): 17.714737422859784
-randrange(10): 8
- choice([1, 2, 3, 4, 5]): 1
- shuffle([1, 2, 3, 4, 5]): None
- sample([1, 2, 3, 4, 5]): [1, 4]

모듈 파일 이름 작성 시 주의 사항

  • 파일 이름을 random.py로 지정하고 사용하는 모듈이 random모듈을 사용하면 TypeError가 발생함
  • import 구문은 가장 먼저 현재 폴더에서 import 뒤에 적어 놓은 파일을 찾음.
  • 만약 찾으면 이를 모듈로 인식하고 읽어 들이므로 random.py라는 이름으로 파일을 저장하고 실행하면 모듈이 아닌 파일을 읽어들여 문제가 발생함
  • 모듈과 같은 이름으로 파일을 지정하지 않아야 함

sys 모듈

  • 시스테모가 관련된 정보를 가지고 있는 모듈
  • 명령 매개변수를 받을 때 많이 사용함
# 모듈 읽음
import sys

# 명령 매개변수 출력
print(sys.argv)
print("---")

# 컴퓨터 환경과 관련된 정보 출력
print("getwindowsversion:()", sys.getwindowsversion())
print("---")
print("copyright:", sys.copyright)
print("---")
print("version:", sys.version)

# 프로그램 강제 종료
sys.exit()

os 모듈

  • 운영체제와 관련된 기능을 가진 모듈
  • 새로운 폴더를 만들거나 폴더 내부의 파일 목록을 보는 일도 os모듈을 활용하여 처리함
# 모듈 읽음
import os

# 기본 정보 몇 개 출력
print("현재 운영체제:", os.name)
print("현재 폴더:", os.getcwd())
print("현재 폴더 내부의 요소:", os.listdir)

# 폴더를 만들고 제거(폴더가 비어 있을 때만 제거 가능)
os.mkdir("hello")
os.rmdir("hello")

# 파일을 생성하고 + 파일 이름을 변경
with open("original.txt", "w") as file:
    file.write("hello")
os.rename("original.txt", "new.txt")

# 파일 제거
os.remove("new.txt")
# os.unlink("new.txt")

# 시스템 명령어 실행
os.system("dir")

datetime 모듈

  • date(날짜), time(시간)과 관련된 모듈로 날짜 형식을 만들 때 자주 사용함
  • strtime()함수를 사용하면 시간을 형식에 맞춰 출력 가능함
  • timedelta()함수를 사용하면 특정 시간의 이전 또는 이후를 구할 수 있음. 그러나 몇 년 후를 구하는 기능은 없음
  • 1년 후를 구할 때는 replace() 함수를 사용해 아예 날짜 값을 교체하는 것이 일반적임
# 모듈 읽음
import datetime
# 현재 시각을 구하고 출력하기
print("# 현재 시각 출력하기")
now = datetime.datetime.now()
print(now.year, "년")
print(now.month, "월")
print(now.day, "일")
print(now.hour, "시")
print(now.minute, "분")
print(now.second, "초")
print()

# 시간 출력 방법
print("# 시간을 포맷에 맞춰 출력하기")
output_a = now.strftime("%Y.%m.%d %H:%M%S")
output_b = "{}년 {}월 {}일 {}시 {}분 {}초".format(now.year, \
    now.month,\
    now.day,\
    now.hour,\
    now.minute,\
    now.second)
output_c = now.strftime("%Y{} %m{} %d{} %H{} %M{} %S{}").format(*"년월이시분초")   # 문자열, 리스트 등에 *을 붙이면 요소 하나하나가 매개변수로 지정됨
print(output_a)
print(output_b)
print(output_c)
print()

# 특정 시간 요소 교체하기
print("#now.replace()로 1년 더하기")
output = now.replace(year=(now.year + 1))
print(output.strftime("%Y{} %m{} %d{} %H{} %M{} %S{}").format(*"년월이시분초"))

# 실행 결과
----------
# 현재 시각 출력하기
20238114467# 시간을 포맷에 맞춰 출력하기
2023.08.11 04:4607
2023811446720230811044607#now.replace()로 1년 더하기
20240811044607

time 모듈

  • 시간과 관련된 기능을 다룰 때는 time 모듈을 사용함
  • time 모듈로 날짜와 관련된 처리를 할 수 있으나 datetime 모듈을 사용하는 경우가 더 많음
  • time 모듈은 유닉스 타임을 구할 때 특정 시간 동안 코드 진행을 정지할 때 많이 사용함

    import time

import time
print("지금부터 5초동안 정지합니다.")
# timesleep()함수는 특정 시간 동안 코드 진행을 정지할 때 사용함
# 매개 변수에는 정지하고 싶은 시간을 초 단위로 입력함
time.sleep(5)
print("프로그램을 종료합니다.")

# 실행 결과
----------
지금부터 5초동안 정지합니다.
프로그램을 종료합니다.

urllib 모듈

  • URL을 다루는 라이브러리이며 'Uniform Resource Locator'을 의미함
  • 네트워크의 자원이 어디에 있는지 확인할 때 사용함
  • 간단하게 웹 브라우저의 주소창에 입력하는 조소라고 이해하면 됨
  • urllib 모듈은 인터넷 주소를 활용할 때 사용하는 라이브러리임
# 모듈을 읽어 들임
from urllib import request

# urlopen() 함수로 구글의 메인 페이지를 읽음
target = request.urlopen("https://google.com")
# read()함수를 호출하면 해당 웹페이지에 있는 내용을 읽어서 가져옴
output = target.read()

# 출력
print(output)

# 실행 결과
---------
# 앞의 b는 바이너리 데이터(binary data)를 의미함
b'<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage"
...생략...


🤔 기본 미션 ) 구문 오류와 예외의 차이 설명하기

구문 오류

  • 프로그램 실행 전에 발생하는 오류
  • 구문 오류가 있으면 프로그램 자체가 실행이 되지 않음

예외

  • 런타임 오류(runtime error)
  • 프로그램 실행 중에 발생하는 오류를 의미
  • try-except 구문으로 처리 가능

구문 오류는 프로그램 실행전에 발생하는 오류로, 구문에 오류가 존재하면 작동하지 않지만 예외는 프로그램은 실행이 되지만 실행 중에 오류가 발생한다.




😮 선택 미션 ) p. 381 3번 문제 풀고 인증하기

output = 10 + "개"           # 1
int("안녕하세요")             # 2
cursor.close)               # 3
[1, 2, 3, 4, 5][10]         # 4
번호오류 or 예외에러 명
1예외TypeError
2예외ValueError
3구문 오류SyntaxError
4예외IndexError
profile
개발을 '잘'하고 싶다는 마음은 항상 늘 지니고 있는 사람

1개의 댓글

comment-user-thumbnail
2023년 8월 10일

감사합니다. 이런 정보를 나눠주셔서 좋아요.

답글 달기