디버깅과 try / except문
디버깅
- 버그의 원인을 찾고
- 발생한 버그를 해결하고
- 비슷한 버그의 재발을 방지하는 것
디버깅은 왜 중요한가?
버그는 사용자의 경험과 직결된다.
버그로 인한 불쾌한 경험은 프로그램의 다른 여러 기능보다 큰 영향을 미친다.
숙련된 개발자라도 한번에 완벽한 코드를 짤 수는 없다.
따라서, 개발자에게는 빠르게 문제를 파악하고 해결하는 능력이 요구된다.
에러의 종류
1. SyntaxError
컴퓨터가 이해할 수 없는 코드
def add_all(numbers):
result = 0
for number in numbers:
result += number
return result
컴퓨터가 읽을 수 조차 없는 코드(여기서는 for문에 콜론(:)이 빠져있다.)
컴퓨터가 이해할 수 없는 부분을 Syntax error로 표시해준다.
2. NameError
정의한 적 없는 변수
def add_all(numbers):
result = 0
for number in numbers:
result += numbre # 'numbre' 오타가 있음
return result
add_all([1, 2, 3])
'numbre'라는 정의한 적 없는 변수가 사용되었다.
3. TypeError
숫자와 'won'을 더할 수 없음
def usd_to_krw(price):
price_in_krw = price * 1100
return price_in_krw + " won" # 숫자와 문자열을 더하려고 해서 오류 발생
usd_to_krw(4.99)
서로 맞지 않는 타입의 무언가를 연산하려고 할 때 발생한다.
위의 경우, 달러를 원으로 변환하는 함수에서 'price_in_krw'라는 숫자를 "won"이라는 문자와 결합시키려 했다.
string(price_in_krw) + "won"으로 적을 시 정상작동한다.
4. IndexError
문자열의 0번째 글자가 존재하지 않음
def first_character(string):
return string[0]
first_character("")
5. ZeroDivisionError
0으로 나눌 수 없음
def average(numbers):
return sum(numbers) / len(numbers)
average([])
그 외에 KeyError, FileNotFoundError 등이 있다.
Python의 try-except 구문 정리
파이썬에서 예외 처리를 할 때는 try-except 구문을 사용한다. 코드를 작성하다 보면 예상치 못한 오류가 발생할 수 있기 때문에, 이 구문을 활용하면 프로그램이 갑자기 중단되는 것을 방지할 수 있다. try-except 구문의 기본적인 사용법부터 다양한 예외 처리 방법까지 정리해 본다.
1. 기본적인 try-except 사용법
가장 기본적인 형태로, 오류가 발생할 가능성이 있는 코드를 try 블록에 넣고, 오류가 발생하면 except 블록이 실행되도록 한다.
try:
number = int(input("숫자를 입력하세요: "))
print(f"입력한 숫자는 {number}입니다.")
except ValueError:
print("유효하지 않은 숫자")
이 코드에서는 사용자가 숫자가 아닌 값을 입력했을 때 ValueError가 발생하고, except 블록이 실행된다. 결과적으로 "유효하지 않은 숫자"라는 메시지가 출력된다.
2. 여러 예외 처리하기
하나의 코드에서 여러 종류의 예외를 처리할 때는 각 예외에 맞게 별도의 except 블록을 사용할 수 있다.
try:
num1 = int(input("첫 번째 숫자를 입력하세요: "))
num2 = int(input("두 번째 숫자를 입력하세요: "))
result = num1 / num2
print(f"결과는 {result}입니다.")
except ValueError:
print("유효한 숫자가 아님")
except ZeroDivisionError:
print("0으로 나눌 수 없습니다.")
여기서는 ValueError와 ZeroDivisionError를 각각 따로 처리하여, 특정 오류에 맞는 메시지를 출력하도록 한다. 예를 들어, 두 번째 숫자에 0을 입력하면 "0으로 나눌 수 없다."라는 메시지가 출력된다.
3. else 블록 사용하기
try 블록이 정상적으로 실행되었을 때 추가적으로 실행할 코드가 있으면 else 블록을 사용한다.
try:
num1 = int(input("첫 번째 숫자를 입력하세요: "))
num2 = int(input("두 번째 숫자를 입력하세요: "))
result = num1 / num2
except (ValueError, ZeroDivisionError) as e:
print(f"오류 발생: {e}")
else:
print(f"연산 성공! 결과는 {result}입니다.")
이 코드는 예외가 발생하지 않았을 때만 else 블록이 실행된다. 정상적으로 연산이 이루어진 경우에만 "연산 성공! 결과는..." 메시지가 출력된다.
4. finally 블록 사용하기
예외가 발생하든 발생하지 않든, 무조건 실행되어야 하는 코드가 있으면 finally 블록을 사용한다. 주로 자원 해제 같은 작업에 유용하다.
try:
file = open('example.txt', 'r')
content = file.read()
print(content)
except FileNotFoundError:
print("파일을 찾을 수 없음")
finally:
file.close()
print("파일을 닫았습니다.")
파일을 열고 읽는 과정에서 오류가 발생해도, finally 블록은 항상 실행되어 파일이 닫히게 된다. 이렇게 하면 파일이 열려 있는 상태로 남아 있는 것을 방지할 수 있다.
5. try-except-else-finally 조합하기
모든 블록을 조합하여 사용하는 경우도 많다. 이 경우 각 블록은 특정한 역할을 수행한다.
try:
num1 = int(input("첫 번째 숫자를 입력하세요: "))
num2 = int(input("두 번째 숫자를 입력하세요: "))
result = num1 / num2
except (ValueError, ZeroDivisionError) as e:
print(f"오류 발생: {e}")
else:
print(f"연산 성공! 결과는 {result}입니다.")
finally:
print("프로그램이 종료되었습니다.")
이 코드에서는 try, except, else, finally 블록이 모두 사용된다. 예외가 발생하더라도 finally 블록은 무조건 실행되며, 프로그램이 종료되었다는 메시지가 출력된다.
예외처리 코드 작성시 주의사항
- 특정 예외를 명시적으로 처리하기 : 광범위한 'except:' 구문은 피하고, 특정 예외에 대해 명확하게 처리할 수 있도록 합니다.
- 'finally' 로 정리 작업 수행하기 : 파일이나 데이터베이스 연결과 같은 리소스를 관리할 때 'finally' 블록에서 항상 정리 작업을 수행합니다.
- 친절한 메시지 출력하기 : 예외를 처리할 때 사용자에게 명확하고 도움이 되는 메시지를 작성하여 제공하도록 합니다.