خطاها: try، except و raise
- پیام خطا (traceback) را بخوانی و بفهمی کجا و چرا است
- با
try/exceptجلوی بسته شدن برنامه را بگیری - خودت با
raise ValueError(...)خطا بسازی nanوinfو دلیل خطرناک بودنشان را بشناسی
خواندن پیام خطا
این را اجرا کن
پیام از پایین خوانده میشود: آخرین خط نوع خطا (ValueError) و دلیل آن را میگوید، خطهای بالاتر کجا (شمارهی خط).
| خطا | معمولاً یعنی |
|---|---|
SyntaxError | نگارش غلط: : یا پرانتز یا کوتیشن جا افتاده |
IndentationError | تورفتگی نامرتب |
NameError | اسمی که تعریف نشده (یا غلط املایی) |
TypeError | نوع نامناسب؛ مثل 'a' + 1 |
ValueError | نوع درست ولی مقدار نامعتبر؛ مثل int('abc') |
KeyError | کلید در دیکشنری نیست |
OSError | مشکل فایل: باز نشد، اجازه نداشت، … |
try / except: گرفتن خطا
خودت امتحان کن
اگر داخل try خطایی رخ دهد، بقیهی try رد میشود و except اجرا میشود. اگر خطا نباشد، except اجرا نمیشود.
چند نوع خطا و خود پیام خطا
خودت امتحان کن
تابع run در خط ۸۵ پروژه تا خط ۹۱ پروژه همهی دکمهها را داخل try اجرا میکند و پیام خطا را با messagebox نشان میدهد. load در خط ۲۰ پروژه تا خط ۲۶ پروژه هم با try جلوی کرش کردن برنامه با فایل خراب را میگیرد.
تبدیل امن
تابع to_number(text) بنویس که متن را با float به عدد تبدیل کند؛ اگر نشد (ValueError) مقدار None برگرداند.
دیدن راهحل (اول خودت تلاش کن)
def to_number(text): try: return float(text) except ValueError: return None
raise: خودت خطا بساز
وقتی ورودی قابل قبول نیست، بهجای ادامه دادن، یک خطا «پرتاب» کن. اجرای تابع همانجا تمام میشود و کسی که تابع را صدا زده میتواند آن را بگیرد:
خودت امتحان کن
همهی متدهای کلاس Shop ورودی را چک میکنند و با raise ValueError متوقف میشوند؛ مثلاً خط ۳۰ پروژه، خط ۳۸ پروژه و خط ۵۷ پروژه.
nan و inf: عددهای عجیب
خودت امتحان کن
هر مقایسهای با nan نادرست است. برای همین چک min(...) < 0 اجازه میداد کاربر nan تایپ کند. راه درست: 0 <= x < float('inf') که nan و inf را هم رد میکند.
این باگ واقعاً در برنامه بود و در خط ۳۱ پروژه درست شد: if not all(0 <= x < float('inf') for x in (buy, sell, qty)):.
چک قیمت
تابع check_price(p) بنویس که اگر p منفی، nan یا بینهایت بود ValueError با پیام 'عدد منفی یا نامعتبر مجاز نیست' پرتاب کند، وگرنه p را برگرداند.
دیدن راهحل (اول خودت تلاش کن)
def check_price(p): if not 0 <= p < float('inf'): raise ValueError('عدد منفی یا نامعتبر مجاز نیست') return p
تابع run کوچک
تابع safe_run(action) بنویس: action() را صدا بزند و 'ok' برگرداند؛ اگر ValueError رخ داد، متن خطا را برگرداند.
دیدن راهحل (اول خودت تلاش کن)
def safe_run(action): try: action() return 'ok' except ValueError as exc: return str(exc)
آزمون این درس
برای گذراندن این درس حداقل ۸۰٪ جواب درست لازم است. هر چند بار خواستی میتوانی دوباره امتحان بدهی.