Skip to main content

์˜ˆ์™ธ ์ฒ˜๋ฆฌ

ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์ค‘ ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ๋ฅผ ์šฐ์•„ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” how to, let's learn. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋Š” ์•ˆ์ •์ ์ธ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“œ๋Š” ํ•ต์‹ฌ.

์˜ˆ์™ธ๋ž€? ๐Ÿค”โ€‹

์˜ˆ์™ธ(Exception)๋Š” ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์ค‘ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜.

# ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ฝ”๋“œ
result = 10 / 0 # ZeroDivisionError
ZeroDivisionError: division by zero

Basic ์˜ˆ์™ธ ์ฒ˜๋ฆฌ: try-exceptโ€‹

๋‹จ์ˆœ ์˜ˆ์™ธ ์ฒ˜๋ฆฌโ€‹

try:
result = 10 / 0
except:
print('์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค')

ํŠน์ • ์˜ˆ์™ธ ์ฒ˜๋ฆฌโ€‹

try:
number = int(input('์ˆซ์ž๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”: '))
result = 10 / number
except ZeroDivisionError:
print('0์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค')
except ValueError:
print('์˜ฌ๋ฐ”๋ฅธ ์ˆซ์ž๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”')

์˜ˆ์™ธ ๋ฉ”์‹œ์ง€ ๋ฐ›๊ธฐโ€‹

try:
file = open('์—†๋Š”ํŒŒ์ผ.txt', 'r')
except FileNotFoundError as e:
print(f'ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: {e}')

try-except-else-finallyโ€‹

์ „์ฒด ๊ตฌ์กฐโ€‹

try:
# ์‹คํ–‰ํ•  ์ฝ”๋“œ
result = 10 / 2
except ZeroDivisionError:
# ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ์‹คํ–‰
print('0์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค')
else:
# ์˜ˆ์™ธ๊ฐ€ ์—†์„ ๋•Œ๋งŒ ์‹คํ–‰
print(f'๊ฒฐ๊ณผ: {result}')
finally:
# ํ•ญ์ƒ ์‹คํ–‰ (์˜ˆ์™ธ ๋ฐœ์ƒ ์—ฌ๋ถ€์™€ ๋ฌด๊ด€)
print('๊ณ„์‚ฐ ์™„๋ฃŒ')

์‹ค์ „ Example: ํŒŒ์ผ ์ฒ˜๋ฆฌโ€‹

def read_file(filename):
file = None
try:
file = open(filename, 'r', encoding='utf-8')
content = file.read()
return content
except FileNotFoundError:
print(f'ํŒŒ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค: {filename}')
return None
except PermissionError:
print(f'Reading Files ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค: {filename}')
return None
finally:
if file:
file.close()
print('ํŒŒ์ผ์„ ๋‹ซ์•˜์Šต๋‹ˆ๋‹ค')

# ์‚ฌ์šฉ Example
content = read_file('data.txt')

์ฃผ์š” ์˜ˆ์™ธ ์ข…๋ฅ˜ ๐Ÿ“‹โ€‹

์ผ๋ฐ˜์ ์ธ ์˜ˆ์™ธโ€‹

# ZeroDivisionError: 0์œผ๋กœ ๋‚˜๋ˆ„๊ธฐ
try:
10 / 0
except ZeroDivisionError:
print('0์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค')

# ValueError: ์ž˜๋ชป๋œ ๊ฐ’
try:
int('abc')
except ValueError:
print('์ˆซ์ž๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค')

# TypeError: ์ž˜๋ชป๋œ ํƒ€์ž…
try:
'๋ฌธ์ž์—ด' + 123
except TypeError:
print('ํƒ€์ž…์ด ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค')

# IndexError: ์ž˜๋ชป๋œ ์ธ๋ฑ์Šค
try:
my_list = [1, 2, 3]
print(my_list[10])
except IndexError:
print('์ธ๋ฑ์Šค๊ฐ€ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚ฌ์Šต๋‹ˆ๋‹ค')

# KeyError: ์—†๋Š” ํ‚ค
try:
my_dict = {'a': 1}
print(my_dict['b'])
except KeyError:
print('ํ‚ค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค')

# AttributeError: ์—†๋Š” ์†์„ฑ
try:
my_str = 'hello'
my_str.append('!')
except AttributeError:
print('ํ•ด๋‹น ์†์„ฑ์ด ์—†์Šต๋‹ˆ๋‹ค')

ํŒŒ์ผ ๊ด€๋ จ ์˜ˆ์™ธโ€‹

# FileNotFoundError: ํŒŒ์ผ ์—†์Œ
try:
open('์—†๋Š”ํŒŒ์ผ.txt', 'r')
except FileNotFoundError:
print('ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค')

# PermissionError: ๊ถŒํ•œ ์—†์Œ
try:
open('/root/file.txt', 'r')
except PermissionError:
print('ํŒŒ์ผ ์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค')

# IsADirectoryError: ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ํŒŒ์ผ๋กœ ์—ด๊ธฐ
try:
open('some_directory', 'r')
except IsADirectoryError:
print('๋””๋ ‰ํ† ๋ฆฌ')

์—ฌ๋Ÿฌ ์˜ˆ์™ธ๋ฅผ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•˜๊ธฐโ€‹

ํŠœํ”Œ๋กœ ๋ฌถ๊ธฐโ€‹

try:
# ์–ด๋–ค ์ž‘์—…
result = risky_operation()
except (ValueError, TypeError, KeyError):
print('๊ฐ’, ํƒ€์ž… ๋˜๋Š” ํ‚ค ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค')

๊ฐ๊ฐ ๋‹ค๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ธฐโ€‹

try:
data = fetch_data()
value = int(data)
except ValueError as e:
print(f'๊ฐ’ ๋ณ€ํ™˜ ์—๋Ÿฌ: {e}')
except ConnectionError as e:
print(f'์—ฐ๊ฒฐ ์—๋Ÿฌ: {e}')
except Exception as e: # ๋ชจ๋“  ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
print(f'์•Œ ์ˆ˜ ์—†๋Š” ์—๋Ÿฌ: {e}')

์˜ˆ์™ธ ๋ฐœ์ƒ์‹œํ‚ค๊ธฐ (raise) ๐Ÿš€โ€‹

Basic raiseโ€‹

def divide(a, b):
if b == 0:
raise ValueError('b๋Š” 0์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค')
return a / b

try:
result = divide(10, 0)
except ValueError as e:
print(e) # 'b๋Š” 0์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค'

์˜ˆ์™ธ ์žฌ๋ฐœ์ƒโ€‹

def process_data(data):
try:
result = complex_operation(data)
except ValueError as e:
print(f'๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ค‘ ์—๋Ÿฌ ๋ฐœ์ƒ: {e}')
raise # ์˜ˆ์™ธ๋ฅผ ๋‹ค์‹œ ๋ฐœ์ƒ์‹œํ‚ด

try:
process_data(invalid_data)
except ValueError:
print('์ƒ์œ„ ๋ ˆ๋ฒจ์—์„œ ์ฒ˜๋ฆฌ')

์˜ˆ์™ธ ์ฒด์ธโ€‹

def load_config():
try:
with open('config.txt', 'r') as f:
return f.read()
except FileNotFoundError as e:
raise RuntimeError('์„ค์ • ํŒŒ์ผ์„ ๋กœ๋“œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค') from e

try:
config = load_config()
except RuntimeError as e:
print(e)
print(f'์›์ธ: {e.__cause__}')

์ปค์Šคํ…€ ์˜ˆ์™ธ ๋งŒ๋“ค๊ธฐ ๐ŸŽจโ€‹

Basic ์ปค์Šคํ…€ ์˜ˆ์™ธโ€‹

class InvalidAgeError(Exception):
"""๋‚˜์ด๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ"""
pass

def set_age(age):
if age < 0 or age > 150:
raise InvalidAgeError(f'์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚˜์ด: {age}')
return age

try:
set_age(-5)
except InvalidAgeError as e:
print(e)

๋ฉ”์‹œ์ง€์™€ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๋Š” ์˜ˆ์™ธโ€‹

class ValidationError(Exception):
"""๋ฐ์ดํ„ฐ ๊ฒ€์ฆ ์‹คํŒจ ์˜ˆ์™ธ"""

def __init__(self, field, value, message):
self.field = field
self.value = value
self.message = message
super().__init__(f'{field}: {message} (๊ฐ’: {value})')

def validate_user(user):
if not user.get('email'):
raise ValidationError('email', user.get('email'), '์ด๋ฉ”์ผ์€ ํ•„์ˆ˜')
if len(user.get('name', '')) < 2:
raise ValidationError('name', user.get('name'), '์ด๋ฆ„์€ 2์ž ์ด์ƒ์ด์–ด์•ผ ')

try:
validate_user({'name': 'A'})
except ValidationError as e:
print(f'ํ•„๋“œ: {e.field}')
print(f'๊ฐ’: {e.value}')
print(f'๋ฉ”์‹œ์ง€: {e.message}')

์˜ˆ์™ธ ๊ณ„์ธต ๊ตฌ์กฐโ€‹

class AppError(Exception):
"""์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ Basic ์˜ˆ์™ธ"""
pass

class DatabaseError(AppError):
"""๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ จ ์˜ˆ์™ธ"""
pass

class NetworkError(AppError):
"""๋„คํŠธ์›Œํฌ ๊ด€๋ จ ์˜ˆ์™ธ"""
pass

class ConnectionError(NetworkError):
"""์—ฐ๊ฒฐ ์‹คํŒจ ์˜ˆ์™ธ"""
pass

# ์‚ฌ์šฉ Example
try:
# ์–ด๋–ค ์ž‘์—…
raise ConnectionError('์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค')
except DatabaseError:
print('๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—๋Ÿฌ')
except NetworkError: # ConnectionError๋„ ํฌํ•จ
print('๋„คํŠธ์›Œํฌ ์—๋Ÿฌ')
except AppError: # ๋ชจ๋“  ์•ฑ ์—๋Ÿฌ ํฌํ•จ
print('์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์—๋Ÿฌ')

assert ๋ฌธ โœ…โ€‹

๋””๋ฒ„๊น…๊ณผ ๊ฐœ๋ฐœ ์ค‘ ์กฐ๊ฑด ๊ฒ€์ฆ์— ์‚ฌ์šฉ.

def calculate_average(numbers):
assert len(numbers) > 0, '๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ์Šต๋‹ˆ๋‹ค'
return sum(numbers) / len(numbers)

# ์ •์ƒ ์ž‘๋™
result = calculate_average([1, 2, 3])
print(result) # 2.0

# AssertionError ๋ฐœ์ƒ
result = calculate_average([]) # AssertionError: ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ์Šต๋‹ˆ๋‹ค

assert vs ์˜ˆ์™ธ ์ฒ˜๋ฆฌโ€‹

# assert: ๊ฐœ๋ฐœ ์ค‘ ๋ฒ„๊ทธ ํ™•์ธ์šฉ (ํ”„๋กœ๋•์…˜์—์„œ๋Š” ๋น„ํ™œ์„ฑํ™” ๊ฐ€๋Šฅ)
def internal_function(value):
assert value > 0, 'value๋Š” ์–‘์ˆ˜์—ฌ์•ผ '
return value * 2

# raise: ์‹ค์ œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ์šฉ (ํ•ญ์ƒ ํ™œ์„ฑํ™”)
def public_api(value):
if value <= 0:
raise ValueError('value๋Š” ์–‘์ˆ˜์—ฌ์•ผ ')
return value * 2

์‹ค์ „ Example ๐Ÿ’กโ€‹

Example 1: ์•ˆ์ „ํ•œ Reading Filesโ€‹

from pathlib import Path

def safe_read_file(file_path, default=None):
"""์•ˆ์ „ํ•˜๊ฒŒ ํŒŒ์ผ์„ ์ฝ๊ณ  ์—๋Ÿฌ ์‹œ Basic๊ฐ’ ๋ฐ˜ํ™˜"""
try:
path = Path(file_path)
return path.read_text(encoding='utf-8')
except FileNotFoundError:
print(f'ํŒŒ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค: {file_path}')
return default
except PermissionError:
print(f'ํŒŒ์ผ ์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค: {file_path}')
return default
except UnicodeDecodeError:
print(f'File Encoding ์˜ค๋ฅ˜: {file_path}')
return default
except Exception as e:
print(f'์•Œ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜: {e}')
return default

# ์‚ฌ์šฉ Example
content = safe_read_file('config.txt', default='# Basic ์„ค์ •')
print(content)

Example 2: ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๊ฒ€์ฆโ€‹

def get_positive_integer(prompt):
"""์–‘์˜ ์ •์ˆ˜๋ฅผ ์ž…๋ ฅ๋ฐ›์„ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต"""
while True:
try:
value = input(prompt)
number = int(value)

if number <= 0:
raise ValueError('์–‘์ˆ˜๋ฅผ ์ž…๋ ฅํ•ด์•ผ ')

return number

except ValueError as e:
if 'invalid literal' in str(e):
print('์ˆซ์ž๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”')
else:
print(e)
except KeyboardInterrupt:
print('\n์ž…๋ ฅ์ด ์ทจ์†Œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค')
return None

# ์‚ฌ์šฉ Example
# age = get_positive_integer('๋‚˜์ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”: ')

Example 3: API ํ˜ธ์ถœ ์žฌ์‹œ๋„โ€‹

import time

class APIError(Exception):
"""API ํ˜ธ์ถœ ์‹คํŒจ"""
pass

def call_api_with_retry(url, max_retries=3, delay=1):
"""API ํ˜ธ์ถœ์„ ์žฌ์‹œ๋„ ๋กœ์ง๊ณผ ํ•จ๊ป˜ ์‹คํ–‰"""
last_error = None

for attempt in range(max_retries):
try:
# ์‹ค์ œ๋กœ๋Š” requests ๋“ฑ์„ ์‚ฌ์šฉ
response = fetch_data(url)

if response.status_code == 200:
return response.data
else:
raise APIError(f'์ƒํƒœ ์ฝ”๋“œ: {response.status_code}')

except (APIError, ConnectionError) as e:
last_error = e
print(f'์‹œ๋„ {attempt + 1}/{max_retries} ์‹คํŒจ: {e}')

if attempt < max_retries - 1:
print(f'{delay}์ดˆ ํ›„ ์žฌ์‹œ๋„...')
time.sleep(delay)
else:
print('๋ชจ๋“  ์žฌ์‹œ๋„ ์‹คํŒจ')

raise APIError(f'API ํ˜ธ์ถœ ์‹คํŒจ: {last_error}')

# ์‚ฌ์šฉ Example
try:
data = call_api_with_retry('https://api.example.com/data')
except APIError as e:
print(f'์ตœ์ข… ์‹คํŒจ: {e}')

Example 4: ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ ์‹œ์Šคํ…œโ€‹

class ValidationError(Exception):
"""๊ฒ€์ฆ ์‹คํŒจ ์˜ˆ์™ธ"""
pass

class Validator:
"""๋ฐ์ดํ„ฐ ๊ฒ€์ฆ class"""

@staticmethod
def validate_email(email):
"""์ด๋ฉ”์ผ ๊ฒ€์ฆ"""
if not email or '@' not in email:
raise ValidationError(f'์œ ํšจํ•˜์ง€ ์•Š์€ ์ด๋ฉ”์ผ: {email}')
return True

@staticmethod
def validate_age(age):
"""๋‚˜์ด ๊ฒ€์ฆ"""
try:
age = int(age)
except (ValueError, TypeError):
raise ValidationError(f'๋‚˜์ด๋Š” ์ˆซ์ž์—ฌ์•ผ : {age}')

if age < 0 or age > 150:
raise ValidationError(f'์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚˜์ด: {age}')
return True

@staticmethod
def validate_phone(phone):
"""์ „ํ™”๋ฒˆํ˜ธ ๊ฒ€์ฆ (๊ฐ„๋‹จํ•œ Example)"""
phone = str(phone).replace('-', '').replace(' ', '')
if not phone.isdigit() or len(phone) < 10:
raise ValidationError(f'์œ ํšจํ•˜์ง€ ์•Š์€ ์ „ํ™”๋ฒˆํ˜ธ: {phone}')
return True

def register_user(user_data):
"""์‚ฌ์šฉ์ž ๋“ฑ๋ก (๊ฒ€์ฆ ํฌํ•จ)"""
errors = []

# ๊ฐ ํ•„๋“œ ๊ฒ€์ฆ
try:
Validator.validate_email(user_data.get('email'))
except ValidationError as e:
errors.append(str(e))

try:
Validator.validate_age(user_data.get('age'))
except ValidationError as e:
errors.append(str(e))

try:
Validator.validate_phone(user_data.get('phone'))
except ValidationError as e:
errors.append(str(e))

# ์—๋Ÿฌ๊ฐ€ ์žˆ์œผ๋ฉด ๋ชจ๋‘ ๋ณด๊ณ 
if errors:
error_msg = '\n'.join(errors)
raise ValidationError(f'๊ฒ€์ฆ ์‹คํŒจ:\n{error_msg}')

return True

# ์‚ฌ์šฉ Example
try:
user = {
'email': 'invalid-email',
'age': -5,
'phone': '123'
}
register_user(user)
except ValidationError as e:
print(e)

Example 5: ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €์™€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌโ€‹

class DatabaseConnection:
"""๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๊ด€๋ฆฌ (Example)"""

def __init__(self, db_name):
self.db_name = db_name
self.connection = None

def __enter__(self):
print(f'{self.db_name}์— ์—ฐ๊ฒฐ ์ค‘...')
try:
self.connection = self.connect(self.db_name)
return self.connection
except Exception as e:
raise ConnectionError(f'DB ์—ฐ๊ฒฐ ์‹คํŒจ: {e}')

def __exit__(self, exc_type, exc_val, exc_tb):
if self.connection:
print(f'{self.db_name} ์—ฐ๊ฒฐ ์ข…๋ฃŒ')
self.connection.close()

# ์˜ˆ์™ธ๋ฅผ ์–ต์ œํ•˜์ง€ ์•Š์Œ
return False

def connect(self, db_name):
# ์‹ค์ œ ์—ฐ๊ฒฐ ๋กœ์ง
return {'connected': True, 'db': db_name}

# ์‚ฌ์šฉ Example
try:
with DatabaseConnection('mydb') as db:
# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…
print(f'์ž‘์—… ์ค‘: {db}')
# ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
# raise ValueError('์ฟผ๋ฆฌ ์‹คํŒจ')
except ConnectionError as e:
print(f'์—ฐ๊ฒฐ ์—๋Ÿฌ: {e}')
except ValueError as e:
print(f'์ž‘์—… ์—๋Ÿฌ: {e}')

Example 6: ๋กœ๊น…๊ณผ ์˜ˆ์™ธ ์ฒ˜๋ฆฌโ€‹

import logging
from datetime import datetime

# ๋กœ๊ฑฐ ์„ค์ •
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

def process_transaction(transaction_id, amount):
"""ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ (๋กœ๊น… ํฌํ•จ)"""
try:
logger.info(f'ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘: {transaction_id}')

# ๊ฒ€์ฆ
if amount <= 0:
raise ValueError(f'์œ ํšจํ•˜์ง€ ์•Š์€ ๊ธˆ์•ก: {amount}')

# ์ฒ˜๋ฆฌ
result = perform_transaction(transaction_id, amount)

logger.info(f'ํŠธ๋žœ์žญ์…˜ ์„ฑ๊ณต: {transaction_id}')
return result

except ValueError as e:
logger.error(f'๊ฒ€์ฆ ์‹คํŒจ [{transaction_id}]: {e}')
raise
except ConnectionError as e:
logger.critical(f'์—ฐ๊ฒฐ ์‹คํŒจ [{transaction_id}]: {e}')
raise
except Exception as e:
logger.exception(f'์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ค๋ฅ˜ [{transaction_id}]')
raise
finally:
logger.debug(f'ํŠธ๋žœ์žญ์…˜ ์ข…๋ฃŒ: {transaction_id}')

def perform_transaction(tid, amount):
# ์‹ค์ œ ํŠธ๋žœ์žญ์…˜ ๋กœ์ง
return {'id': tid, 'amount': amount, 'status': 'completed'}

# ์‚ฌ์šฉ Example
try:
result = process_transaction('TXN001', 1000)
except ValueError:
print('์œ ํšจํ•˜์ง€ ์•Š์€ ํŠธ๋žœ์žญ์…˜')
except Exception:
print('ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ์‹คํŒจ')

์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค ๐ŸŒŸโ€‹

1. ๊ตฌ์ฒด์ ์ธ ์˜ˆ์™ธ๋ฅผ ๋จผ์ € ์ฒ˜๋ฆฌโ€‹

# ์ข‹์Œ
try:
operation()
except FileNotFoundError:
# ๊ตฌ์ฒด์  ์ฒ˜๋ฆฌ
pass
except IOError:
# ๋” ์ผ๋ฐ˜์ ์ธ ์ฒ˜๋ฆฌ
pass
except Exception:
# ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ์ฒ˜๋ฆฌ
pass

# ๋‚˜์จ - ์ ˆ๋Œ€ ๋„๋‹ฌํ•˜์ง€ ์•Š์Œ
try:
operation()
except Exception:
pass
except FileNotFoundError: # ๋„๋‹ฌํ•˜์ง€ ์•Š์Œ!
pass

2. ๋นˆ except ํ”ผํ•˜๊ธฐโ€‹

# ๋‚˜์จ
try:
risky_operation()
except: # ๋ชจ๋“  ์˜ˆ์™ธ๋ฅผ ์žก์Œ (KeyboardInterrupt๋„!)
pass

# ์ข‹์Œ
try:
risky_operation()
except Exception as e: # ์‹œ์Šคํ…œ ์˜ˆ์™ธ๋Š” ์ œ์™ธ
logger.error(f'์—๋Ÿฌ ๋ฐœ์ƒ: {e}')

3. ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€์— ์ปจํ…์ŠคํŠธ ํฌํ•จโ€‹

# ๋‚˜์จ
raise ValueError('์œ ํšจํ•˜์ง€ ์•Š์Œ')

# ์ข‹์Œ
raise ValueError(f'์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚˜์ด: {age} (0-150 ์‚ฌ์ด์—ฌ์•ผ ํ•จ)')

4. ์กฐ์šฉํžˆ ์‹คํŒจํ•˜์ง€ ์•Š๊ธฐโ€‹

# ๋‚˜์จ - ์—๋Ÿฌ๋ฅผ ์ˆจ๊น€
try:
important_operation()
except:
pass # ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ๋ชจ๋ฆ„

# ์ข‹์Œ - ์ตœ์†Œํ•œ ๋กœ๊น…
try:
important_operation()
except Exception as e:
logger.error(f'์ค‘์š”ํ•œ ์ž‘์—… ์‹คํŒจ: {e}')
raise # ๋˜๋Š” ์ ์ ˆํ•œ ์ฒ˜๋ฆฌ

Frequently Asked Questions โ“โ€‹

Q1: except Exception๊ณผ except๋งŒ ์“ฐ๋Š” ๊ฒƒ์˜ ์ฐจ์ด๋Š”?โ€‹

# except: ๋ชจ๋“  ๊ฒƒ์„ ์žก์Œ (BaseException)
try:
operation()
except:
# KeyboardInterrupt, SystemExit๋„ ์žก์Œ (์œ„ํ—˜!)
pass

# except Exception: ์ผ๋ฐ˜ ์˜ˆ์™ธ๋งŒ ์žก์Œ
try:
operation()
except Exception:
# ์‹œ์Šคํ…œ ์ข…๋ฃŒ ์‹œ๊ทธ๋„์€ ํ†ต๊ณผ์‹œํ‚ด (์•ˆ์ „)
pass

Q2: ์˜ˆ์™ธ๋ฅผ ๋ฌด์‹œํ•ด๋„ ๋˜๋Š” ๊ฒฝ์šฐ๋Š”?โ€‹

# ์„ ํƒ์  ๊ธฐ๋Šฅ์ด๊ณ  ์‹คํŒจํ•ด๋„ ๊ดœ์ฐฎ์„ ๋•Œ
try:
import optional_module
use_advanced_feature()
except ImportError:
# module์ด ์—†์–ด๋„ ๊ณ„์† ์‹คํ–‰
use_basic_feature()

# ํŒŒ์ผ์ด ์—†๋Š” ๊ฒƒ์ด ์ •์ƒ์ผ ๋•Œ
try:
config = load_config()
except FileNotFoundError:
config = default_config()

Q3: raise์™€ raise e์˜ ์ฐจ์ด๋Š”?โ€‹

try:
operation()
except ValueError as e:
# raise: ์›๋ž˜ ์Šคํƒ ํŠธ๋ ˆ์ด์Šค ์œ ์ง€ (๊ถŒ์žฅ)
raise

# raise e: ์ƒˆ๋กœ์šด ์Šคํƒ ํŠธ๋ ˆ์ด์Šค ์ƒ์„ฑ
# raise e

Q4: finally ์—†์ด ๋ฆฌ์†Œ์Šค๋ฅผ ์ •๋ฆฌํ•˜๋Š” how to์€?โ€‹

# with ๋ฌธ ์‚ฌ์šฉ (๊ถŒ์žฅ)
with open('file.txt', 'r') as f:
content = f.read()
# ์ž๋™์œผ๋กœ ํŒŒ์ผ์ด ๋‹ซํž˜

Q5: ์—ฌ๋Ÿฌ ์˜ˆ์™ธ๋ฅผ ํ•˜๋‚˜๋กœ ๋ฌถ๋Š” how to์€?โ€‹

# Python 3.11+ : ExceptionGroup
try:
operations()
except* ValueError as eg:
# ์—ฌ๋Ÿฌ ValueError๋ฅผ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌ
for e in eg.exceptions:
print(e)

# ์ด์ „ ๋ฒ„์ „: ์ˆ˜๋™์œผ๋กœ ์ˆ˜์ง‘
errors = []
for item in items:
try:
process(item)
except ValueError as e:
errors.append(e)

if errors:
print(f'{len(errors)}๊ฐœ์˜ ์—๋Ÿฌ ๋ฐœ์ƒ')

Next Stepsโ€‹

  • ํŒŒ์ผ ์ž…์ถœ๋ ฅ: ํŒŒ์ผ ์ž‘์—…์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ํ™œ์šฉํ•˜๊ธฐ
  • ๋‚ ์งœ์™€ ์‹œ๊ฐ„: ์‹œ๊ฐ„ ๊ด€๋ จ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
  • logging module: ์˜ˆ์™ธ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๊ธฐ๋กํ•˜๋Š” how to
  • ๋””๋ฒ„๊น… ๊ธฐ๋ฒ•: pdb๋ฅผ ์‚ฌ์šฉํ•œ ์˜ˆ์™ธ ๋ถ„์„