λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄/Python

파이썬 μ˜ˆμ™Έμ²˜λ¦¬(Exception)의 λͺ¨λ“  것

by μ„œμ•„λž‘πŸ˜ 2023. 12. 10.

 

 

 

λŒ€ν‘œμ μΈ μ˜ˆμ™Έ 상황

ν”νžˆ λ°œμƒν•˜λŠ” μ˜ˆμ™Έμƒν™©μ„  κ°„λ‹¨νžˆ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

  • μ—†λŠ” 파일 μ—΄κΈ°
>>> f = open("abc.txt", 'r')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'abc.txt'
  • Zero division
>>> 4 / 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
  • index error
>>> a = [1, 2, 3]
>>> a[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

 

try-except

νŒŒμ΄μ¬μ—μ„œ μ˜ˆμ™Έ μ²˜λ¦¬λŠ” μ½”λ“œ μ‹€ν–‰ 쀑에 λ°œμƒν•˜λŠ” μ˜ˆμ™Έλ‚˜ 였λ₯˜ 상황에 λŒ€μ²˜ν•˜κΈ° μœ„ν•œ λ©”μ»€λ‹ˆμ¦˜μ„ λ§ν•©λ‹ˆλ‹€. μ˜ˆμ™ΈλŠ” ν”„λ‘œκ·Έλž¨μ˜ 정상적인 흐름을 λ°©ν•΄ν•˜κ³  였λ₯˜ λ©”μ‹œμ§€λ₯Ό λ°œμƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. μ˜ˆμ™Έ 처리λ₯Ό 톡해 μ΄λŸ¬ν•œ 상황에 λŒ€μ‘ν•˜κ³  ν”„λ‘œκ·Έλž¨μ΄ gracefulν•˜κ²Œ μ²˜λ¦¬ν•  수 μžˆλ„λ‘ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ˜ˆμ™Έ μ²˜λ¦¬λŠ” try, except, else, finally λ“±μ˜ ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„λ©λ‹ˆλ‹€.

try:
    # μ˜ˆμ™Έκ°€ λ°œμƒν•  수 μžˆλŠ” μ½”λ“œ 블둝
    # μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ©΄ except λΈ”λ‘μœΌλ‘œ 이동
    # μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ§€ μ•ŠμœΌλ©΄ else 블둝 μ‹€ν–‰
except μ˜ˆμ™Έμ’…λ₯˜ as μ˜ˆμ™Έλ³€μˆ˜:
    # μ˜ˆμ™Έ 처리 μ½”λ“œ
    # μ˜ˆμ™Έ μ’…λ₯˜μ— 따라 λ‹€λ₯΄κ²Œ 처리 κ°€λŠ₯
else:
    # μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ§€ μ•Šμ•˜μ„ λ•Œ μ‹€ν–‰λ˜λŠ” μ½”λ“œ
finally:
    # μ˜ˆμ™Έ λ°œμƒ 여뢀와 상관없이 항상 μ‹€ν–‰λ˜λŠ” μ½”λ“œ

 

μ˜ˆμ‹œλ₯Ό 톡해 각 뢀뢄을 μ„€λͺ…ν•˜κ² μŠ΅λ‹ˆλ‹€.

try:
    # μ˜ˆμ™Έκ°€ λ°œμƒν•  수 μžˆλŠ” μ½”λ“œ
    x = 10 / 0  # ZeroDivisionError λ°œμƒ
except ZeroDivisionError as e:
    # ZeroDivisionErrorκ°€ λ°œμƒν–ˆμ„ λ•Œ μ‹€ν–‰λ˜λŠ” μ½”λ“œ
    print(f"Error: {e}")
else:
    # μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ§€ μ•Šμ•˜μ„ λ•Œ μ‹€ν–‰λ˜λŠ” μ½”λ“œ
    print("No error")
finally:
    # μ˜ˆμ™Έ λ°œμƒ 여뢀와 상관없이 항상 μ‹€ν–‰λ˜λŠ” μ½”λ“œ
    print("Finally block")

이 μ½”λ“œλŠ” ZeroDivisionErrorκ°€ λ°œμƒν•  경우 ν•΄λ‹Ή μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•˜κ³  μ—λŸ¬ λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•©λ‹ˆλ‹€. λ§Œμ•½ μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ§€ μ•ŠμœΌλ©΄ else 블둝이 μ‹€ν–‰λ˜κ³ , λ§ˆμ§€λ§‰μœΌλ‘œ finally 블둝이 항상 μ‹€ν–‰λ©λ‹ˆλ‹€.

 

μΆ”κ°€μ μœΌλ‘œ, except λΈ”λ‘μ—μ„œ μ—¬λŸ¬ μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•˜κ±°λ‚˜ λͺ¨λ“  μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•˜λŠ” 방법도 μžˆμŠ΅λ‹ˆλ‹€.

try:
    # μ˜ˆμ™Έκ°€ λ°œμƒν•  수 μžˆλŠ” μ½”λ“œ
    x = 10 / 0  # ZeroDivisionError λ°œμƒ
except (ZeroDivisionError, ValueError) as e:
    # μ—¬λŸ¬ μ˜ˆμ™Έλ₯Ό λ™μ‹œμ— μ²˜λ¦¬ν•˜λŠ” μ½”λ“œ
    print(f"Error: {e}")
except Exception as e:
    # λͺ¨λ“  μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•˜λŠ” μ½”λ“œ
    print(f"Unexpected error: {e}")

μ˜ˆμ™Έ μ²˜λ¦¬λŠ” ν”„λ‘œκ·Έλž¨μ˜ μ•ˆμ •μ„±μ„ ν–₯μƒμ‹œν‚€κ³  예기치 μ•Šμ€ 상황에 λŒ€μ²˜ν•˜λŠ”λ° μ€‘μš”ν•œ λ„κ΅¬μž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ λ„ˆλ¬΄ λ§Žμ€ μ˜ˆμ™Έλ₯Ό λ„ˆλ¬΄ 일반적으둜 μ²˜λ¦¬ν•˜λŠ” 것은 디버깅을 μ–΄λ ΅κ²Œ λ§Œλ“€ 수 μžˆμœΌλ―€λ‘œ μ‹ μ€‘ν•˜κ²Œ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

 

try-finally

보톡 try-finally둜 κ΅¬μ„±λœ κ΅¬μ‘°λŠ” finally μ ˆμ—μ„œ μ‚¬μš©ν•œ λ¦¬μ†ŒμŠ€λ₯Ό closeν•  λ•Œ 많이 μ‚¬μš©λ©λ‹ˆλ‹€.

# try_finally.py
try:
    f = open('foo.txt', 'w')
    # 무언가λ₯Ό μˆ˜ν–‰ν•œλ‹€.

    (... μƒλž΅ ...)

finally:
    f.close()  # 쀑간에 였λ₯˜κ°€ λ°œμƒν•˜λ”λΌλ„ 무쑰건 μ‹€ν–‰λœλ‹€.

 

였λ₯˜ νšŒν”Ό

νŠΉμ • 였λ₯˜κ°€ λ°œμƒν–ˆμ„ λ•Œ κ·Έλƒ₯ ν†΅κ³Όμ‹œμΌœμ•Όν•  λ•Œλ„ μžˆμŠ΅λ‹ˆλ‹€. 그럴 λ•Œ passλ₯Ό μ‚¬μš©ν•΄μ„œ νšŒν”Όν•©λ‹ˆλ‹€.

# error_pass.py
try:
    f = open("λ‚˜μ—†λŠ”νŒŒμΌ", 'r')
except FileNotFoundError:
    pass

try λ¬Έ μ•ˆμ—μ„œ FileNotFoundErrorκ°€ λ°œμƒν•  경우, passλ₯Ό μ‚¬μš©ν•˜μ—¬ 였λ₯˜λ₯Ό κ·Έλƒ₯ νšŒν”Όν•˜λ„λ‘ μž‘μ„±ν•œ μ˜ˆμ œμž…λ‹ˆλ‹€.

 

였λ₯˜ κ°•μ œλ‘œ λ°œμƒμ‹œν‚€κΈ°

νŒŒμ΄μ¬μ€ raise λͺ…λ Ήμ–΄λ₯Ό μ‚¬μš©ν•΄ 였λ₯˜λ₯Ό κ°•μ œλ‘œ λ°œμƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄ Bird 클래슀λ₯Ό μƒμ†λ°›λŠ” μžμ‹ ν΄λž˜μŠ€λŠ” λ°˜λ“œμ‹œ flyλΌλŠ” ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•˜λ„λ‘ λ§Œλ“€κ³  싢은 경우(κ°•μ œλ‘œ κ·Έλ ‡κ²Œ ν•˜κ³  싢은 경우)κ°€ μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

# error_raise.py
class Bird:
    def fly(self):
        raise NotImplementedError

Bird 클래슀λ₯Ό μƒμ†λ°›λŠ” μžμ‹ ν΄λž˜μŠ€λŠ” λ°˜λ“œμ‹œ fly ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•œλ‹€λŠ” μ˜μ§€λ₯Ό 보여 μ€λ‹ˆλ‹€. C++의 μˆœμˆ˜κ°€μƒν•¨μˆ˜, μžλ°”μ˜ μΈν„°νŽ˜μ΄μŠ€ ν•¨μˆ˜μ™€ 같은 κ°œλ…μž…λ‹ˆλ‹€. λ§Œμ•½ μžμ‹ ν΄λž˜μŠ€κ°€ fly ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•˜μ§€ μ•Šμ€ μƒνƒœλ‘œ fly ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•œλ‹€λ©΄ μ–΄λ–»κ²Œ λ κΉŒμš”?

NotImplementedErrorλŠ” νŒŒμ΄μ¬μ— 이미 μ •μ˜λ˜μ–΄ μžˆλŠ” 였λ₯˜λ‘œ, κΌ­ μž‘μ„±ν•΄μ•Ό ν•˜λŠ” 뢀뢄이 κ΅¬ν˜„λ˜μ§€ μ•Šμ•˜μ„ 경우 μΌλΆ€λŸ¬ 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚€κΈ° μœ„ν•΄ μ‚¬μš©ν•©λ‹ˆλ‹€.

class Eagle(Bird):
    pass

eagle = Eagle()
eagle.fly()     # 였λ₯˜ λ°œμƒ

Eagle ν΄λž˜μŠ€λŠ” flyλ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌλ””μ΄ν•˜μ§€ μ•Šμ•˜μœΌλ―€λ‘œ eagle.fly()λ₯Ό ν˜ΈμΆœν•˜λŠ” μˆœκ°„ NotImplementedErrorκ°€ λ°œμƒν•©λ‹ˆλ‹€.

 

μ»€μŠ€ν…€ μ˜ˆμ™Έ λ§Œλ“€κΈ°

νŠΉμˆ˜ν•œ 경우, ν•„μš”ν•œ κ²½μš°μ— 직접 μ˜ˆμ™Έλ₯Ό λ§Œλ“€μ–΄μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

# error_make.py
class MyError(Exception):
    pass

μ˜ˆμ™Έ ν΄λž˜μŠ€λŠ” 파이썬 λ‚΄μž₯ 클래슀인 Exception 클래슀λ₯Ό μƒμ†ν•˜μ—¬ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.

def say_nick(nick):
    if nick == '바보':
        raise MyError()
    print(nick)

say_nick("μ²œμ‚¬")
say_nick("바보")

μœ„ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ “μ²œμ‚¬”κ°€ ν•œ 번 좜λ ₯된 ν›„ MyErrorκ°€ λ°œμƒν•©λ‹ˆλ‹€.

μ²œμ‚¬
Traceback (most recent call last):
  File "...", line 11, in <module>
    say_nick("바보")
  File "...", line 7, in say_nick
    raise MyError()
__main__.MyError

μ˜ˆμ™Έ λ‚΄μš©μž…λ‹ˆλ‹€.

try:
    say_nick("μ²œμ‚¬")
    say_nick("바보")
except MyError:
    print("ν—ˆμš©λ˜μ§€ μ•ŠλŠ” 별λͺ…μž…λ‹ˆλ‹€.")

# μ²œμ‚¬
# ν—ˆμš©λ˜μ§€ μ•ŠλŠ” 별λͺ…μž…λ‹ˆλ‹€.

MyError에 λŒ€ν•΄ μ˜ˆμ™Έ μ²˜λ¦¬ν•œ λͺ¨μŠ΅μž…λ‹ˆλ‹€.

 


 

μ°Έκ³ : 점프 투 파이썬

λŒ“κΈ€